<?php

declare(strict_types=1);

namespace App\Resource\Service;

use App\Common\Constants\ErrorCode;
use App\Common\Constants\Stakeholder;
use App\Common\Service\Arr;
use App\Common\Service\BaseService;
use App\Order\Model\KzRefundLogModel;
use App\Order\Model\OrderGoodsModel;
use App\Order\Model\OrderModel;
use App\Order\Model\RefundGoodsModel;
use App\Order\Model\WxRefundLogModel;
use App\Order\Service\Order\OrderMiniService;
use App\Resource\Model\GoodsModel;
use App\Resource\Model\LeaderSorting;
use App\Resource\Model\LeaderSortingLog;
use App\Resource\Model\ShopGroupModel;
use App\Resource\Model\ShopModel;
use App\Resource\Event\UpdateShop;
use App\Resource\Model\TeamLeaderCommissionRecord;
use App\Resource\Model\TeamLeaderModel;
use App\Resource\Model\TeamLeaderWriteOffLogs;
use App\User\Model\UserModel;
use App\User\Service\MemberService;
use Carbon\Carbon;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use PhpCsFixer\Fixer\DoctrineAnnotation\DoctrineAnnotationBracesFixer;
use Psr\EventDispatcher\EventDispatcherInterface;

class TeamLeaderService extends BaseService
{


    /**
     * @Inject
     * @var BaseService
     */
    private $baseService;

    /**
     * @Inject
     * @var Arr
     */
    private $arrFunction;
    /**
     * @Inject
     * @var MemberService
     */
    private $memverService;

    public function __construct()
    {
      parent::__construct();
    }

    /**
     * @param array $params
     * @param int $perPage
     * @param string[] $field
     *
     * @return array
     *
     * 排序为：待审核的在最前面，同状态下先提交的排前面
     */
    public function getList(array $params = [], int $perPage = 15, $field = ['*'])
    {
        $query = TeamLeaderModel::query();
        if (in_array($params['status'], ['1', '2', '3', '4'])) {
            $query->where('leader.status', '=', $params['status']);
        }
        $list = $query
            ->from('hf_team_leader as leader')
            ->leftJoin('store_shop as shop', 'shop.shop_id', '=', 'leader.shop_id')
            ->when($params['name'] ?? 0, function ($query, $name) {
                $query->whereRaw('INSTR(leader.name, ?) > 0', [$name]);
            })
            ->when($params['phone'] ?? 0, function ($query, $phone) {
                return $query->where('leader.phone', $phone);
            })
            ->when($params['start_time'] ?? 0, function ($query, $startTime) {
                return $query->where('leader.created_at', '>=', $startTime);
            })
            ->when($params['end_time'] ?? 0, function ($query, $endTime) {
                return $query->where('leader.created_at', '<=', $endTime);
            })
            ->when($params['shop_id'] ?? 0, function ($query, $shopId) {
                return $query->where('leader.shop_id', '=', $shopId);
            })
            ->selectRaw('
                leader.id,
                leader.name, 
                leader.delivery_address, 
                leader.detail_address, 
                leader.longitude, 
                leader.latitude, 
                leader.phone, 
                leader.shop_id, 
                leader.status, 
                leader.created_at,
                shop.shop_name
            ')
            ->oldest('status')
            ->oldest('created_at')
            ->paginate($perPage);

        return ['code' => ErrorCode::SUCCESS, 'data' => $list];
    }

    /**
     * @param int $id
     * @param array|string[] $field
     *
     * @return array
     */
    public function getInfoById(int $id, array $field = ['*'])
    {
        $res = TeamLeaderModel::query()->where('id', $id)->select($field)->first();
        if (!$res) {
            return ['code' => ErrorCode::NOT_EXIST];
        }
        $shopName = ShopModel::query()->where('shop_id', $res->shop_id)->value('shop_name');
        $approver = UserModel::query()->where('id', $res->approver)->value('username');
        $res->shop_name = $shopName ?? '未知店铺';
        $res->approver = $approver ?? null;

        return ['code' => ErrorCode::SUCCESS, 'data' => $res];
    }

    /**
     * @param array $params
     *
     * @return array
     */
    public function apply(array $params = [])
    {
        if (!empty($params['sid'])) {
            // 检测分享人的身份
            $sharerIdentity = $this->sharerDetection($params['sid']);
            if ($sharerIdentity['code']) {
                return ['code' => $sharerIdentity['code']];
            }
        }

        $teamLeaderStatus = TeamLeaderModel::query()->where(['mid' => $params['mid']])->select(['status', 'id'])->first();
        // 手机验证码验证
        $checkPhone = $this->checkSmsCode($params['phone'], $params['phone_code']);
        if ($checkPhone['code']) {
            return ['code' => $checkPhone['code']];
        }
        if (!$teamLeaderStatus) {
            // 手机号重复检测
            $isPhoneExist = TeamLeaderModel::query()->where('phone', $params['phone'])->exists();
            if ($isPhoneExist) {
                return ['code' => ErrorCode::PHONE_EXIST];
            }
            // 从未提交过申请，添加信息
            $res = TeamLeaderModel::query()->create([
                'name' => $params['name'],
                'delivery_address' => $params['delivery_address'],
                'detail_address' => $params['detail_address'],
                'longitude' => $params['longitude'],
                'latitude' => $params['latitude'],
                'phone' => $params['phone'],
                'shop_id' => $params['shop_id'],
                'mid' => $params['mid'],
                'sid' => $params['sid'] ?? null,
                'status' => Stakeholder::LEADER_STATUS_UNDER_REVIEW,
            ]);
            $list = ['id' => $res->id, 'status' => $res->status];
        } elseif ($teamLeaderStatus->status == Stakeholder::LEADER_STATUS_REJECTED) {
            $isPhoneExist = TeamLeaderModel::query()->where('phone', $params['phone'])->where('mid', '<>', $params['mid'])->exists();
            if ($isPhoneExist) {
                return ['code' => ErrorCode::PHONE_EXIST];
            }
            // 之前申请被驳回，需要修改信息
            $res = TeamLeaderModel::query()->where('mid', $params['mid'])->update([
                'name' => $params['name'],
                'delivery_address' => $params['delivery_address'],
                'detail_address' => $params['detail_address'],
                'longitude' => $params['longitude'],
                'latitude' => $params['latitude'],
                'phone' => $params['phone'],
                'shop_id' => $params['shop_id'],
                'mid' => $params['mid'],
                'sid' => $params['sid'] ?? null,
                'status' => Stakeholder::LEADER_STATUS_UNDER_REVIEW,
            ]);
            $list = ['id' => $teamLeaderStatus->id, 'status' => 1];
        } elseif (in_array($teamLeaderStatus->status, [Stakeholder::LEADER_STATUS_IN_BUSINESS, Stakeholder::LEADER_STATUS_OUT_OF_BUSINESS])) {
            return ['code' => ErrorCode::HAS_BEEN_TEAM_LEADER];
        } else {
            // status=1,审核中
            return ['code' => ErrorCode::TEAMLEADE_STATUS_SUBMIT];
        }
        if ($res) {
            // 操作成功，则删除缓存
            $this->smsRedis->del('sms-' . $params['phone']);
            return ['code' => ErrorCode::SUCCESS, 'data' => $list];
        }
        return ['code' => ErrorCode::NOT_IN_FORCE];
    }

    /**
     * 检测团长分享人的身份
     * @param $sid
     * @return array
     */
    private function sharerDetection($sid)
    {
        $sidStatus = TeamLeaderModel::query()->where(['mid' => $sid])->value('status');
        if (!in_array($sidStatus, [Stakeholder::LEADER_STATUS_IN_BUSINESS, Stakeholder::LEADER_STATUS_OUT_OF_BUSINESS]))
            return ['code' => ErrorCode::SHARER_TEAM_LEADER_STATUS_FAILED];

        return ['code' => ErrorCode::SUCCESS, 'data' => []];
    }

    /**
     * 手机验证码检测
     * @param string $phone
     * @param string $code
     *
     * @return array
     */
    public function checkSmsCode(string $phone, string $code)
    {
        $cachePhoneCode = $this->smsRedis->get('sms-' . $phone);    // 123456|false
        if (!$cachePhoneCode) {
            return ['code' => ErrorCode::PHONE_CODE_INVALID];
        } elseif ($code != $cachePhoneCode) {
            return ['code' => ErrorCode::PHONE_CODE_ERROR];
        }
        return ['code' => ErrorCode::SUCCESS];
    }

    /**
     * @param array $params
     *
     * @return array
     */
    public function check(array $params = [])
    {
        // 只有待审核 status = 1 的条目才能进行此操作
//        $status = TeamLeaderModel::query()->where('id', $params['id'])->value('status');
//        if ($status != Stakeholder::LEADER_STATUS_UNDER_REVIEW) {
//            return ['code' => ErrorCode::TEAMLEADE_STATUS_CAN_NOT_CHECK];
//        }

        $rejectReason = $params['reject_reason'] ?? null;

        // 若审核通过，需要为团长加上营业时间，默认为所绑定店铺的营业时间
        if($params['status'] == Stakeholder::LEADER_STATUS_OUT_OF_BUSINESS){
            $shopTime =  ShopModel::query() -> where('shop_id', $params['shop_id']) -> first(['start_time', 'end_time']);
            $shopStartTime = $shopTime -> start_time ?? null;
            $shopEndTime = $shopTime -> end_time ?? null;
        }

        $res = TeamLeaderModel::query()->where('id', $params['id'])->update([
            'status' => $params['status'],
            'reject_reason' => $rejectReason,
            'name' => $params['name'],
            'delivery_address' => $params['delivery_address'],
            'detail_address' => $params['detail_address'],
            'longitude' => $params['longitude'],
            'latitude' => $params['latitude'],
            'phone' => $params['phone'],
            'shop_id' => $params['shop_id'],
            'passing_time' => $params['passing_time'] ?? null,
            'approver' => $this->jwt->setScene('default')->getParserData()['uid'] ?? null,
            'opening_time' => $shopStartTime ?? null,
            'closing_time' => $shopEndTime ?? null,
        ]);
        if ($res) {
            // 若审核成功，则更新次日达附近店铺缓存
            if ($params['status'] == Stakeholder::LEADER_STATUS_OUT_OF_BUSINESS) {
                $map['cate'] = 'crd';
                $this->eventDispatcher->dispatch(new UpdateShop($map));
            }

            return ['code' => ErrorCode::SUCCESS, 'data' => [], 'info' => ['target_id' => $params['id']]];
        }

        return ['code' => ErrorCode::NOT_IN_FORCE];
    }

    /**
     * 获取核销过后，被冻结的佣金
     *
     * @param $leader_id
     * @param string $order_no
     * @return int
     */
    public function getFreezeOrderCommission($leader_id, $order_no = '*'): int
    {
        $order_nos = $this->resourceRedis->keys("tl:[{$leader_id}]:$order_no");
        $arr = $this->resourceRedis->mget($order_nos);
        if ($arr) {
            $arr = array_values($arr);
            return intval(array_sum($arr));
        }
        return 0;
    }

    /**
     * 退佣金
     *
     * @param $order_no
     * @param $leader_id
     * @param $commission
     * @return mixed
     */
    public function backCommission($order_no, $leader_id, $commission = 0)
    {
        try {
            Db::transaction(function () use ($leader_id, $order_no, $commission) {
//                $exists = TeamLeaderCommissionRecord::query()->where('order_no', $order_no)->where('type', TeamLeaderCommissionRecord::TYPE_BACK_COMMISSION)->first();
//                if ($exists) {
//                    throw new \Exception('此订单已成功退还佣金');
//                }
                $order = OrderModel::query()->find($order_no);
                if (!$order) {
                    throw new \Exception('错误的订单号码');
                }
                if ($order->status < 4) {
                    throw new \Exception('该订单未完成核销');
                }
                $refundTimeout = $this->resourceRedis->get("tl:{$leader_id}:{$order_no}");
                if (!$refundTimeout) {
                    throw new \Exception('超出退款有效期，预约时间 48 小时之内~');
                }
                $commission = $commission ? $commission * 100 : $refundTimeout;
                if ($commission <= 0) {
                    throw new \Exception('佣金不能 ≤ 0');
                }
                // 有效佣金
                $effectiveCommission = $this->resourceRedis->set("tl:{$leader_id}:$order_no", ($refundTimeout - $commission));
                if ($effectiveCommission < 0) {
                    throw new \Exception(ErrorCode::getMessage(ErrorCode::NOT_IN_FORCE));
                }
                $leader = TeamLeaderModel::query()->find($leader_id);
                $leader->decrement('commission_amount', $commission);
                $leader->decrement('add_up_commission', $commission);
                // 佣金明细
                TeamLeaderCommissionRecord::query()->create([
                    'shop_id' => $order['shop_id'],
                    'leader_id' => $leader_id,
                    'serial_no' => date('YmdHis') . rand(10000, 99999),
                    'expend' => $commission,
                    'order_no' => $order_no,
                    'type' => TeamLeaderCommissionRecord::TYPE_BACK_COMMISSION,
                    'balance' => $leader->commission_amount,
                    'withdraw_status' => 0,
                ]);
            });
        } catch (\Exception $e) {
            return ['code' => ErrorCode::NOT_IN_FORCE, 'msg' => $e->getMessage()];
        }
        return ['code' => ErrorCode::SUCCESS, 'msg' => 'success', 'data' => []];
    }

    /**
     * 扫描自提码获取订单信息
     *
     * @param $id
     * @param $code
     * @return array
     */
    public function scanCodeGetOrderInfo($id, $code)
    {
        try {
            $order = OrderModel::query()->where('write_off_code', $code)->first();
            if (!$order)
                throw new \Exception('核销码错误');
            if ($order->is_deleted == 1)
                throw new \Exception('该订单已删除');
            if (!$order->member)
                throw new \Exception('不存在的的用户');
            if ($order->leader_id != $id)
                throw new \Exception('该订单此团长无法进行核销');
            $goodsFiled = ['id', 'goods_logo', 'goods_title', 'selling_price', 'number', 'take_num'];
            $data = [
                'order_no' => $order['order_no'],
                'status' => $order['status'],
                'money' => $order['total_price'],
                'member_name' => $order->member->nickname,
                'member_phone' => $order->member->phone,
                'delivery_address' => $order->teamLeader->delivery_address,
                'detail_address' => $order->teamLeader->detail_address,
                'goods_list' => $order->goods()->select($goodsFiled)->get(),
            ];
            return ['success' => true, 'msg' => 'success', 'data' => $data];
        } catch (\Exception $e) {
            return ['success' => false, 'msg' => $e->getMessage()];
        }
    }

    /**
     * 核销备用
     *
     * @param $id
     * @param $order_no
     * @param $goods_list
     * @return array
     */
    public function writeOffBak($id, $order_no, $goods_list)
    {
        $order = OrderModel::query()->where('order_no', $order_no)->first();
        if ($order['status'] == 4) {
            return [
                'code' => ErrorCode::ORDER_VERIFICATION_STATUS,
                'outcome' => [],
            ];
        }
        if (strtotime($order['appointment_date']) > time()) {
            return [
                'code' => ErrorCode::CAN_T_ADVANCE_TAKE,
                'outcome' => [],
            ];
        }
        $status = true;
        $result = [];
        foreach ($goods_list as $v) {
            try {
                $_result = [
                    'id' => $v['id'],
                    'msg' => '成功',
                    'success' => true,
                ];
                $obj = OrderGoodsModel::query()->find($v['id']);
                if (!$obj) {
                    throw new \Exception($v['id'] . ' 找不到');
                }
                if (($obj->number - ($obj->take_num + $v['take_num'])) < 0) {
                    throw new \Exception($v['id'] . ' 不能多拿');
                }

                $res = true;
                Db::transaction(function () use ($obj, $v, &$res) {
                    $obj->increment('take_num', $v['take_num']);
                    TeamLeaderWriteOffLogs::query()->create([
                        'order_goods_id' => $v['id'],
                        'order_no' => $obj['order_no'],
                        'number' => $v['take_num'],
                        'remarks' => '',
                    ]);
                });
                if (!$res) {
                    throw new \Exception($v['id'] . ' 核销失败');
                }

            } catch (\Exception $e) {
                $status = false;
                $_result['msg'] = $e->getMessage();
                $_result['success'] = false;
                continue;
            } finally {
                $result[] = $_result;
            }
        }
        ($result && $status) && $this->generate_commission($id, $order_no);
        return [
            'code' => ErrorCode::SUCCESS,
            'outcome' => $result,
        ];
    }

    /**
     *
     * 核销方法
     *
     * @param $id
     * @param $order_no
     * @param $goods_list
     * @return array
     */
    public function writeOff($id, $order_no, $goods_list)
    {
        try {
            $order = OrderModel::query()->where('order_no', $order_no)->first();
            if ($order['status'] == 4) {
                throw new \Exception('当前订单已经被核销过了', ErrorCode::ORDER_VERIFICATION_STATUS);
            }
            if (strtotime($order['appointment_date']) > time()) {
                throw new \Exception('不能提前核销', ErrorCode::CAN_T_ADVANCE_TAKE);
            }
            // 已完成自提的商品
            $done = 0;
            // 核销日志
            $writeOffLogs = [];
            // 需要更新提货数量的数据
            $updateData = [];
            $orderGoodsIds = array_column($goods_list, 'id');
            $wantTakeNumbers = array_column($goods_list, 'take_num', 'id');
            $goodsList = OrderGoodsModel::query()
                ->select('id', 'order_no', 'number', 'take_num')
                ->whereIn('id', $orderGoodsIds)
                ->get();
            if ($goodsList) {
                $goodsList = $goodsList->toArray();
                $orderNos = array_column($goodsList, 'order_no', 'id');
                $goodsNumbers = array_column($goodsList, 'number', 'id');
                $takeNumbers = array_column($goodsList, 'take_num', 'id');
                foreach ($goodsNumbers as $orderGoodsId => $number) {
//                    var_dump('购买数量：'.$goodsNumbers[$orderGoodsId]);
//                    var_dump('已自提：'.$takeNumbers[$orderGoodsId]);
//                    var_dump('要自提：'.$wantTakeNumbers[$orderGoodsId]);
                    // 需要插入到数据库的数值
                    $changeNumber = $takeNumbers[$orderGoodsId] + $wantTakeNumbers[$orderGoodsId];
                    // 超出购买的数量
                    $overNum = $number - $changeNumber;
                    if (($number == $takeNumbers[$orderGoodsId]) || $overNum == 0) {
                        $done++;
                    }
                    // 提货数量小于等于 0
                    if ($changeNumber <= 0)
                        continue;
                    // 提货数量超出购买数量
                    if ($overNum < 0)
                        break;
                    $updateData[] = [
                        'id' => $orderGoodsId,
                        'take_num' => $changeNumber,
                    ];
                    $writeOffLogs[] = [
                        'order_goods_id' => $orderGoodsId,
                        'order_no' => $orderNos[$orderGoodsId],
                        'number' => $wantTakeNumbers[$orderGoodsId],
                        'created_at' => date('Y-m-d H:i:s'),
                        'updated_at' => date('Y-m-d H:i:s'),
                    ];
                }
            }
            if (!$writeOffLogs || !$updateData) {
                throw new \Exception('核销的数据不正确', ErrorCode::WRITE_OFF_DATA_IS_ILLEGAL);
            }
            Db::transaction(function () use ($id, $order_no, $goodsList, $done, $writeOffLogs, $updateData) {
                $this->updateBatch('store_order_goods', $updateData);
                if ($done == count($goodsList)) {
                    $commissionRes = $this->generate_commission($id, $order_no);
                    if (!$commissionRes['success']) {
                        throw new \Exception($commissionRes['msg'], ErrorCode::NOT_IN_FORCE);
                    }
                    TeamLeaderWriteOffLogs::query()->insert($writeOffLogs);
                }
            });
            return ['code' => ErrorCode::SUCCESS];
        } catch (\Exception $e) {
            return ['code' => $e->getCode(), 'msg' => $e->getMessage()];
        }
    }

    /**
     * 生成佣金
     *
     * @param $leader_id
     * @param $order_no
     * @return array
     */
    public function generate_commission($leader_id, $order_no)
    {
        try {
            Db::beginTransaction();
            // 更改订单状态
            $order = OrderModel::query()->where('order_no', $order_no)->first();
            if (!$order->update(['status' => 4,'write_off_code_status' => 2, 'complete_date' => date('Y-m-d H:i:s')])) {
                throw new \Exception('更改订单状态失败');
            }
            // 佣金大于 0 才产生记录
            if ($order['order_commission'] > 0) {
                // 返回佣金
                $commission = $order['order_commission'] * 100;
                $leader = TeamLeaderModel::query()->find($leader_id);
                if (!$leader->increment('commission_amount', $commission)) {
                    throw new \Exception('返回佣金失败');
                }
                // 判断距离用户提交的自提时间是否已经超过 48 小时
                $pastTime = time() - strtotime($order['appointment_date']);
                if ($pastTime < (48 * 3600)) {
                    $this->resourceRedis->set("tl:{$leader_id}:{$order_no}", $commission, $pastTime);
                }
                if (!$leader->increment('add_up_commission', $commission)) {
                    throw new \Exception('累计佣金失败');
                }
                // 佣金明细
                $recordData = [
                    'shop_id' => $order['shop_id'],
                    'leader_id' => $leader_id,
                    'serial_no' => date('YmdHis') . rand(10000, 99999),
                    'income' => $commission,
                    'order_no' => $order_no,
                    'type' => TeamLeaderCommissionRecord::TYPE_INCOME_COMMISSION,
                    'balance' => $leader->commission_amount,
                    'withdraw_status' => 0,
                ];
                $record = TeamLeaderCommissionRecord::query()->create($recordData);
                if (!$record) {
                    throw new \Exception('记录提现日志失败');
                }
            }
            Db::commit();
            return ['success' => true, 'msg' => '生成佣金！'];
        } catch (\Exception $e) {
            Db::rollBack();
            return ['success' => false, 'msg' => $e->getMessage()];
        }
    }

    /**
     * 获取单天订单信息
     *
     * @param $id
     * @param $date
     * @param string[] $filed
     * @return array
     */
    public function getOrderDataDay($id, $date)
    {
//        $where = [];
        $where = ['leader_id' => $id, 'status' => 4];
        $filed = [
            Db::raw('right(complete_date,8) as time'),
            'order_no',
            'total_price',
            'order_commission',
        ];
        $list = OrderModel::query()->where($where)->whereDate('complete_date', $date)->select($filed)->orderBy('time', 'desc')->paginate(20);
        $count = $list->total();
        if ($count > 0) {
            $arr = $list->items();
            $total_amount = $this->setCentsToYuan($arr, 'total_price');
            $total_commission = $this->setCentsToYuan($arr, 'order_commission');
        }
        return [
            'count' => $count,
            'total_amount' => $total_amount ?? 0,
            'total_commission' => $total_commission ?? 0,
            'list' => $list->items(),
        ];
    }

    /**
     * 获取核销订单
     *
     * @param $id
     * @param $date
     * @return array
     */
    public function getDayWriteOffOrder($id, $date)
    {
        !is_array($date) && $date = [$date];
        $date = " ' " . join("','", array_values($date)) . " ' ";
        // 所有核销订单
        $list = OrderModel::query()
            ->from('store_order as order')
            ->leftJoin('store_order_goods as og', 'og.order_no', '=', 'order.order_no')
            ->select([
                Db::raw('count(1) as total_number'),
                Db::raw('DATE_FORMAT(complete_date,"%H:%i") as time'),
                Db::raw('DATE(`order`.`complete_date`) as date'),
                Db::raw('CONVERT(SUM(og.dis_price - og.refund_number * og.goods_dis_price),DECIMAL(15,2)) as total_price'),
                Db::raw('CONVERT(SUM((og.number - og.refund_number) * og.commission),DECIMAL(15,2)) as order_commission'),
            ])
            ->where('order.leader_id', $id)
            ->where('order.is_pay', 1)
            ->where('order.platform_type', 2)
            ->where('order.write_off_code_status', 2)
            ->whereRaw("date(`order`.`complete_date`) in ($date)")
            ->whereRaw("og.dis_price - og.refund_number * og.goods_dis_price > 0")
            ->groupBy(['order.order_no'])
            ->paginate(10);
        $count = $list->total();
        if ($count > 0) {
            $arr = $list->items();
            $total_amount = $this->setCentsToYuan($arr, 'total_price');
            $total_commission = $this->setCentsToYuan($arr, 'order_commission');
        }
        return [
            'count'            => $count,
            'total_amount'     => $total_amount ?? 0,
            'total_commission' => $total_commission ?? 0,
            'list'             => $list->items(),
        ];
    }

    /**
     * 获取区间订单数据
     *
     * @param $id
     * @param $interval
     * @param string[] $filed
     * @return array
     */
    public function getIntervalOrderData($id, $interval)
    {
        $filed = [
            Db::raw('left(complete_date,10) as date'),
            Db::raw('count(1) as total_number'),
            Db::raw('sum(total_price) as total_price'),
            Db::raw('sum(order_commission) as order_commission'),
        ];
        $list = OrderModel::query()
            ->select($filed)
            ->where('leader_id', $id)
            ->where('status', 4)
            ->whereBetween('complete_date', $interval)
            ->groupBy('date')
            ->get();
        $count = $list->count();
        if ($count > 0) {
            $arr = $list->toArray();
            $total_number = array_sum(array_column($arr, 'total_number'));
            $total_amount = $this->setCentsToYuan($arr, 'total_price');
            $total_commission = $this->setCentsToYuan($arr, 'order_commission');
        }
        return [
            'count' => $total_number ?? 0,
            'total_amount' => $total_amount ?? 0,
            'total_commission' => $total_commission ?? 0,
            'list' => $list,
        ];
    }

    /**
     * 待自提数量
     *
     * @param $id
     * @return int
     */
    public function wait_takeaway_num($id)
    {
        return OrderModel::query()->where('leader_id', $id)->where('status', 3)->where('order_type_status', 2)->count();
    }


    /**
     * 获取待自检数量
     *
     * @param $id
     * @return array
     */
    public function getQuantityToBeSorted($id)
    {
        $_today = date('Y-m-d');
        $_yesterday = date('Y-m-d', strtotime('-1 day'));

        $list = LeaderSorting::query()
            ->where('leader_id', $id)
            ->selectRaw('sorting_time,sum(num) as total_num,sum(sorting_num) as sorting_num')
            ->where(function ($q) use ($_today, $_yesterday) {
                $q->whereDate('sorting_time', $_today)->orWhereDate('sorting_time', $_yesterday);
            })
            ->groupBy(['sorting_time'])
            ->get();

        if ($list) {
            $list = collect($list)->keyBy('sorting_time')->toArray();
        }

        $today = isset($list[$_today]['total_num']) ? $list[$_today]['total_num'] - $list[$_today]['sorting_num'] : 0;
        $yesterday = isset($list[$_yesterday]['total_num']) ? $list[$_yesterday]['total_num'] - $list[$_yesterday]['sorting_num'] : 0;

        return [
            'today'     => $today < 0 ? 0 : $today,
            'yesterday' => $yesterday < 0 ? 0 : $yesterday,
        ];
    }

    /**
     * 把集合里面的字段 单位分转换成元
     *
     * @param $arr
     * @param $column
     * @return float|int
     */
    public function setCentsToYuan($arr, $column)
    {
        $res = array_column($arr, $column);
        $res = array_map(function ($v) {
            return $v * 100;
        }, $res);
        return (array_sum($res)) / 100;
    }

    /**
     * 提现
     *
     * @param int $id
     * @param $amount
     * @return array
     */
    public function withdraw(int $id, $amount)
    {
        // 提现金额（分）
        $expend = $amount * 100;
        try {
//            if (date("w") != 3)
//                throw new \Exception('提现申请只能在每周的周三');
            if ($expend < 10000)
                throw new \Exception('提现金额不能小于 100 元');
            $leader = TeamLeaderModel::query()->find($id);
            if (!$leader)
                throw new \Exception('尝试查找不存在的团长');
            if (!$leader->account_name || !$leader->account_bank || !$leader->bank_card_number)
                throw new \Exception('请先设置完整的提现账户');
            if ($expend > ($leader->commission_amount - $leader->frozen_amount - $this->getFreezeOrderCommission($id)))
                throw new \Exception('佣金账户余额不足');
            Db::beginTransaction();
            if (!$leader->increment('frozen_amount', $expend))
                throw new \Exception('冻结账户余额失败');
            $recordData = [
                'shop_id' => $leader['shop_id'],
                'leader_id' => $id,
                'serial_no' => date('YmdHis') . rand(10000, 99999),
                'expend' => $expend,
                'type' => TeamLeaderCommissionRecord::TYPE_WITHDRAW,
                'withdraw_status' => 0,
            ];
            $record = TeamLeaderCommissionRecord::query()->create($recordData);
            if (!$record)
                throw new \Exception('记录提现日志失败');
            Db::commit();
            return ['success' => true, 'msg' => '提现成功'];
        } catch (\Exception $e) {
            Db::rollBack();
            return ['success' => false, 'msg' => $e->getMessage()];
        }
    }

    /**
     * 设置
     *
     * @param int $id
     * @param array $data
     * @return bool
     */
    public function setting(int $id, array $data)
    {
        $leader = TeamLeaderModel::query()->find($id);
        if (!$leader) {
            return false;
        }
        return $leader->fill($data)->update($data);
    }

    /**
     * 获取佣金记录
     *
     * @param int $id
     * @param string[] $filed
     * @return mixed
     */
    public function commissionRecords(int $id, $filed = ['*'])
    {
        return TeamLeaderCommissionRecord::query()->where('leader_id', $id)->orderByRaw('updated_at desc')->paginate(20, $filed);
    }

    /**
     * @param int $id
     * @param array $params
     *
     * @return array
     */
    public function edit(int $id, array $params = [])
    {
        // 对团长的编辑操作，只能是通过团长资质审核，且未被驳回的。
        $leaderInfo = TeamLeaderModel::query()->find($id, ['status']);
        if (!in_array($leaderInfo->status, [Stakeholder::LEADER_STATUS_IN_BUSINESS, Stakeholder::LEADER_STATUS_OUT_OF_BUSINESS])) {
            return ['code' => ErrorCode::TEAM_LEADER_STATUS_FAILED];
        }

//        // 对修改的状态进行检测，若要将团长状态修改为营业中，则需要判断团长资料是否完善
//        if($params['status'] == 3 && !$leaderInfo->bank_card_number){
//            return ['code' => ErrorCode::LEADER_INCOMPLETE_INFORMATION];
//        }

        $res = TeamLeaderModel::query()->where('id', $id)->update([
            'name' => $params['name'],
            'delivery_address' => $params['delivery_address'],
            'detail_address' => $params['detail_address'],
            'longitude' => $params['longitude'],
            'latitude' => $params['latitude'],
            'phone' => $params['phone'],
            'shop_id' => $params['shop_id'],
            'status' => $params['status'],
        ]);
        if ($res) {
            // 更新附近店铺团长的 Redis 数据
            $this->resourceRedis->del('nearShop-crd');
            return ['code' => ErrorCode::SUCCESS, 'data' => [], 'info' => ['target_id' => $id]];
        }

        return ['code' => ErrorCode::NOT_IN_FORCE];
    }

    /**
     * 团长订单
     * @param array $field
     * @param array $param
     * @param int $id
     * @param int $perPage
     * @return \Hyperf\Contract\LengthAwarePaginatorInterface
     */
    public function teamOrder(array $field, array $param, int $id, int $perPage)
    {
      return  $this->container->get(OrderMiniService::class)->teamOrder($field,$param,$id,$perPage);
    }

    public function teamOrderDetail(string $order_no, int $id)
    {
        $orderDetail = $this->container->get(OrderMiniService::class)->teamOrderDetail($order_no,$id);
        $orderDetail['username'] = $this->memverService->findValue(['mid' => $orderDetail['mid']],'nickname')??'';
        $team = TeamLeaderModel::where(['id' => $orderDetail['leader_id']])->select(['name', 'delivery_address', 'detail_address'])->first();
        $orderDetail['shop'] = ['name' => $team['name'], 'address' => $team['delivery_address'] . $team['detail_address']];
        return $orderDetail;
    }

    /**
     * @param array $params
     * @param int $perPage
     * @param string[] $field
     *
     * @return array
     */
    public function withdrawList(array $params = [], int $perPage = 15, $field = ['*'])
    {
        //  YYYY-MM-DD HH:mm:ss - YYYY-MM-DD HH:mm:ss
        if (!empty($params['apply_time']) && strlen(trim($params['apply_time'])) > 24) {
            $params['apply_time'] = [
                trim(substr($params['apply_time'], 0, 19)),
//                trim(substr($params['apply_time'], -19)) . ' 23:59:59'
                trim(substr($params['apply_time'], -19))
            ];
        }

        if (!empty($params['withdraw_time']) && strlen(trim($params['withdraw_time'])) > 24) {
            $params['withdraw_time'] = [
                trim(substr($params['withdraw_time'], 0, 19)),
                trim(substr($params['withdraw_time'], -19))
            ];
        }

        $query = TeamLeaderCommissionRecord::query();

        if (in_array($params['withdraw_status'] ?? null, [Stakeholder::LEADER_WITHDRAW_STATUS_NO, Stakeholder::LEADER_WITHDRAW_STATUS_YES])) {
            $query->where('record.withdraw_status', '=', $params['withdraw_status']);
        }
        $query->where('record.type', '=', Stakeholder::WITHDRAW_TYPE);
        $list = $query
            ->from('hf_team_leader_commission_record as record')
            ->leftJoin('hf_team_leader as leader', 'leader.id', '=', 'record.leader_id')
            ->when($params['serial_no'] ?? 0, function ($query, $serialNo) {
                return $query->where('record.serial_no', $serialNo);
            })
            ->when($params['phone'] ?? 0, function ($query, $phone) {
                return $query->where('leader.phone', $phone);
            })
            ->when($params['apply_time'] ?? 0, function ($query, $applyTime) {
                return $query->whereBetween('record.created_at', $applyTime);
            })
            ->when($params['withdraw_time'] ?? 0, function ($query, $withdrawTime) {
                return $query->whereBetween('record.withdraw_time', $withdrawTime);
            })
            ->when($params['account_bank'] ?? 0, function ($query, $accountBank) {
                return $query->where('leader.account_bank', $accountBank);
            })
            ->selectRaw('
                record.id,
                record.serial_no,
                record.created_at,
                record.updated_at,
                record.withdraw_time,
                (CONVERT(record.expend / 100,DECIMAL(10,2))) as expend,
                record.withdraw_status,
                leader.name,
                leader.phone,
                leader.account_name,
                leader.account_bank,
                leader.bank_card_number
            ')
            ->paginate($perPage, $field);

        if (!$list->isEmpty()) {
            $bankName = $this->getBankList();
            foreach ($list as $key => $val) {
                $val->account_bank = $bankName[$val->account_bank]['name'] ?? '未知';
            }
        }

        return ['code' => ErrorCode::SUCCESS, 'data' => $list];
    }

    /**
     * @param int $id
     * @param array|string[] $field
     *
     * @return array
     */
    public function withdrawInfo(int $id, array $field = ['*'])
    {
        $res = TeamLeaderCommissionRecord::query()
            ->from('hf_team_leader_commission_record as record')
            ->leftJoin('hf_team_leader as leader', 'leader.id', '=', 'record.leader_id')
            ->selectRaw('
                record.id,
                record.serial_no,
                record.withdraw_certificate,
                record.withdraw_remark,
                record.created_at,
                record.updated_at,
                record.withdraw_time,
                (CONVERT(record.expend / 100,DECIMAL(10,2))) as expend,
                record.withdraw_status,
                leader.name,
                leader.phone,
                leader.account_name,
                leader.account_bank,
                leader.bank_card_number
            ')
            ->where('record.id', '=', $id)
            ->where('record.type', '=', Stakeholder::WITHDRAW_TYPE)
            ->first();

        $bankName = $this->getBankList();
        $res->account_bank = $bankName[$res->account_bank]['name'] ?? '未知';

        if (!$res) {
            return ['code' => ErrorCode::NOT_EXIST];
        }

        return ['code' => ErrorCode::SUCCESS, 'data' => $res];
    }

    /**
     * 获取银行列表，并以银行 ID 作为键
     * @return array
     */
    public function getBankList()
    {
        return $bankName = array_column(TeamLeaderModel::banks(), null, 'id');
    }

    /**
     * @param int $id 提现申请 ID
     * @param array|string[] $field
     *
     * @return array
     *
     * 提现操作：
     * 1、账户余额 = 账户余额 - 本次提现金额
     * 2、冻结金额 = 冻结金额 - 本次提现余额
     * 3、添加转账凭证和转账备注，以及转账时间
     * 4、剩余佣金 = 账户余额
     * 5、本条提现记录的状态改为已审核
     */
    public function withdrawApprove(array $params = [])
    {
        $recordId = $params['id'];
        $recordInfo = TeamLeaderCommissionRecord::query()->where(['id' => $recordId, 'type' => Stakeholder::WITHDRAW_TYPE, 'withdraw_status' => Stakeholder::LEADER_WITHDRAW_STATUS_NO])->first();
        if (!$recordInfo) {
            return ['code' => ErrorCode::NOT_EXIST];
        }
        $leaderInfo = TeamLeaderModel::query()->where(['id' => $recordInfo->leader_id])->first();

        $commissionAmount = $leaderInfo->commission_amount;   // 账户余额
        $frozenAmount = $leaderInfo->frozen_amount;   // 冻结金额
        $expend = $recordInfo->expend;   // 提现金额

        // 提现金额不能小于 100 元
        if ($expend < 10000) {
            return ['code' => ErrorCode::TEAMLEADE_WITHDRAW_AMOUNT_ERROR];
        }
        // 当次提现金额不能大于已审核（冻结）金额
        if ($expend > $frozenAmount) {
            return ['code' => ErrorCode::BALANCE_OF_ACCOUNT_INSUFFICIENT];
        }
        // 账户余额要大于本次提现金额
        if ($expend > $commissionAmount) {
            return ['code' => ErrorCode::INSUFFICIENT_ACCOUNT_BALANCE];
        }
        try {
            DB::transaction(function () use ($recordInfo, $leaderInfo, $commissionAmount, $frozenAmount, $expend, $params) {
                $leaderInfo->commission_amount = $commissionAmount - $expend;
                $leaderInfo->frozen_amount = $frozenAmount - $expend;
                $leaderInfo->save();
                $recordInfo->withdraw_certificate = $params['withdraw_certificate'];
                $recordInfo->withdraw_remark = $params['withdraw_remark'] ?? null;
                $recordInfo->withdraw_time = date('Y-m-d H:i:s');
                $recordInfo->balance = $leaderInfo->commission_amount;
                $recordInfo->withdraw_status = 1;
                $recordInfo->save();
            });
        } catch (\Exception $e) {
            return ['code' => ErrorCode::NOT_IN_FORCE];
        }
        return ['code' => ErrorCode::SUCCESS, 'data' => [], 'info' => ['target_id' => $recordId]];
    }


    public function teamLeaderByShop(array $where, array $field = ['*'], string $leaderName='')
    {
        $query = TeamLeaderModel::query()->select($field)->where($where)->with(['member'=>function($query){$query->select(['face_url','mid']);}])->whereIn('status',[3,4]);
        if($leaderName){
            $query->whereRaw("CONCAT(name, phone) like  '%{$leaderName}%'");
        }
        return $query->get()->toArray();
    }

    /**
     * 分拣列表
     * @param array $where
     * @param string $field
     * @return array
     */
    public function leaderSortingList(array $where,string $field='*')
    {
        $list = LeaderSorting::selectRaw($field)
            ->where($where)
            ->get()
            ->toArray();
        return $list;
    }
    /**
     * 分拣列表
     * @param int $shopId
     * @param int $perPage
     * @param int $page
     * @return array
     * @author lulongfei
     */
    public function sortingOrderList(int $shopId, int $perPage, int $page,string $leaderName)
    {
        $_startTime =  LeaderSorting::where(['shop_id' => $shopId])->orderBy('sorting_time','desc')->value('sorting_time');
        $startTime = $_startTime?$_startTime:date('Y-m-d');
        //每次加载30天数据
        $start_timestamp = strtotime($startTime)-($page-1)*$perPage*86400*3;
        $end_timestamp = $start_timestamp-$page*86400*$perPage*3;
        $start = date('Y-m-d',$start_timestamp);
        $end = date("Y-m-d", $end_timestamp);
        $teamleader = $this->teamLeaderByShop(['shop_id' => $shopId], ['name', 'id', 'shop_id', 'delivery_address', 'detail_address','phone','mid'],$leaderName);
        if(empty($teamleader)){
            return ['code'=>ErrorCode::NOT_EXIST,'msg'=>'团长信息不存在'];
        }
        $leaderIdsArr = array_column($teamleader, null,'id');
        $list = LeaderSorting::selectRaw("sum(num) as num,sorting_time,leader_id,status,goods_id")
            ->groupBy(['sorting_time', 'leader_id','goods_id'])
            ->orderBy('sorting_time', 'desc')
            ->havingRaw("sorting_time > '$end' and sorting_time <= '$start'")
            ->whereIn('leader_id',array_keys($leaderIdsArr))
            ->get()
            ->toArray();
        $_data = [];
        foreach ($list as $k => $v) {
            $list[$k]['leader'] = [
                'name'=>$leaderIdsArr[$list[$k]['leader_id']]['name'],
                'phone'=>$leaderIdsArr[$list[$k]['leader_id']]['phone'],
                'face_url'=>$leaderIdsArr[$list[$k]['leader_id']]['member']['face_url'],
                'address'=>$leaderIdsArr[$list[$k]['leader_id']]['delivery_address'].$leaderIdsArr[$list[$k]['leader_id']]['detail_address']
            ];
            $_data[$list[$k]['sorting_time']][$list[$k]['leader_id']][] = $list[$k];
        }
        $data =[];
        foreach ($_data as $key=>$item) {
            //$key  时间
            $leaderArr = [];
            foreach ($item as $k => $v) {//$k  团长id

                $_sortingStatus = array_unique(array_column($v, 'status'));
                if (count($_sortingStatus) > 1) {
                    $sortingStatus = '部分分拣';
                } else {
                    $sortingStatus = $_sortingStatus[0] ==1  ? '待分拣' : ($_sortingStatus[0] == 2 ? '部分分拣' : '已分拣');
                }
                $leaderArr[] = [
                    'num'=>array_sum(array_column($v, 'num')),
                    'leader_id'=>$k,
                    'time'=>$key,
                    'leader'=>$v[0]['leader'],
                    'sorting_status'=>$sortingStatus
                ];

            }
            $data[] = ['time' => $key, 'info' => $leaderArr];
        }
        return ['code'=>ErrorCode::SUCCESS,'data'=>$data];
    }
    /**
     * 团长分拣详情 根据日期获取
     * @param int $shopId
     * @param int $leaderId
     * @param string $times
     * @return array
     * @author lulongfei
     */
    public function sortingLeaderDetail(int $shopId, int $leaderId, string $times)
    {
        $teamleaderService = (new TeamLeaderService());
        $teamleaderArr = $teamleaderService->teamLeaderByShop(['shop_id' => $shopId,'id'=>$leaderId], ['name', 'id', 'shop_id', 'delivery_address', 'detail_address','phone','mid']);
        if(empty($teamleaderArr)){
            return ['code'=>ErrorCode::NOT_EXIST,'msg'=>'团长信息不存在'];
        }
        $teamleader = $teamleaderArr[0];
        $list = $teamleaderService->leaderSortingList(['sorting_time' => $times, 'leader_id' => $leaderId, 'shop_id' => $shopId],"num,sorting_time,leader_id,status,goods_id,sorting_num,id");
        $data = [];
        $goods = $this->getSortingGoodsList(array_column($list,'goods_id'),'id as goods_id,title as goods_title,logo as goods_logo');
        $goodsById = array_column($goods,null,'goods_id');
        foreach ($list as $k =>$v){
            $list[$k] =  array_merge($v,$goodsById[$v['goods_id']]);
            $num = $list[$k]['num'] - $list[$k]['sorting_num'];
            $list[$k]['need_sorting_num'] = $num>0?$num:0;
        }
        $data['goods'] = $list;
        $_sortingStatus = array_unique(array_column($list, 'status'));
        if (count($_sortingStatus) > 1) {
            $sortingStatus = '部分分拣';
        } else {
            $sortingStatus = $_sortingStatus[0] == 1 ? '待分拣' : ($_sortingStatus[0] == 2 ? '部分分拣' : '已分拣');
        }
        $data['sorting_status'] = $sortingStatus;
        $data['order_num'] = array_sum(array_column($list, 'num'));
        $data['leader'] = [
            'name' => $teamleader['name'],
            'phone' => $teamleader['phone'],
            'face_url'=>$teamleader['member']['face_url'],
            'address' => $teamleader['delivery_address'] . $teamleader['detail_address']
        ];
        return ['code'=>ErrorCode::SUCCESS,'data'=>$data];
    }

    /**
     * 分拣商品数据
     * @param array $whereIn
     * @param string $field
     */
    public function getSortingGoodsList(array $whereIn,$field='*')
    {
        return GoodsModel::whereIn('id',$whereIn)->selectRaw($field)->get()->toArray();
    }
    /**
     *
     * 添加分拣记录
     * @param int $shopId
     * @param int $leaderId
     * @param string $time
     * @param array $goods
     * @return array
     * @author lulongfei
     */
    public function saveSortingLog(int $shopId, int $leaderId, string $time, array $goods)
    {
        $sortingDetail = $this->sortingLeaderDetail($shopId, $leaderId, $time);
        if($sortingDetail['code']){
            return ['code' => $sortingDetail['code'], 'msg' => $sortingDetail['msg']];
        }
        $_needGoodsArr = $sortingDetail['data']['goods'];
        if(empty($_needGoodsArr)){
            return ['code' => ErrorCode::NOT_IN_FORCE, 'msg' => '没有待分拣商品'];
        }
        $needGoodsArr = array_column($_needGoodsArr, null, 'goods_id');
        $data = [];
        $leaderSortingData = [];
        foreach ($goods as $v) {

            if ((isset($needGoodsArr[$v['goods_id']]) &&$v['need_sorting_num'] > $needGoodsArr[$v['goods_id']]['need_sorting_num']) || empty($v['need_sorting_num'])) {
                return ['code' => ErrorCode::NOT_IN_FORCE, 'msg' => '商品：' . $needGoodsArr[$v['goods_id']]['goods_title'] . '  分拣数量有误'];
            }
            $leaderSortingData[] =[
                'id'=>$needGoodsArr[$v['goods_id']]['id'],
                'sorting_num'=>$needGoodsArr[$v['goods_id']]['sorting_num'] +$v['need_sorting_num'],
                'status'=> $needGoodsArr[$v['goods_id']]['sorting_num'] +$v['need_sorting_num']==$needGoodsArr[$v['goods_id']]['num']?3:2
            ];
            $data[] = [
                'shop_id' => $shopId,
                'leader_id' => $leaderId,
                'sorting_time' => $time,
                'created_at' => date('Y-m-d H:i:s'),
                'goods_id' => $v['goods_id'],
                'num' => $v['need_sorting_num'],
                'goods_num' => $needGoodsArr[$v['goods_id']]['num'],
            ];
        }
        $sql = 'UPDATE hf_leader_sorting SET ';
        $sql1 =' sorting_num = CASE ';
        $sql2 =' status = CASE ';
        $whereIn = [];
        foreach ($leaderSortingData as $v){
            $whereIn[] =$v['id'];
            $sql1 .= "WHEN id = {$v['id']} THEN {$v['sorting_num']} ";
            $sql2 .= "WHEN id = {$v['id']} THEN {$v['status']} ";
        }
        $sql .=$sql1.'END,'.$sql2.'END ,'.' updated_at = now() WHERE id IN ('.implode(',',$whereIn).')';
        Db::beginTransaction();
        try {
            Db::update($sql);
            LeaderSortingLog::insert($data);
            Db::commit();
            return ['code' => ErrorCode::SUCCESS];
        }catch (\Throwable $ex){
            Db::rollBack();
            return ['code' => ErrorCode::NOT_IN_FORCE];
        }
    }

    /*
     *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *
     *                                                *团长数据分析*                                                      *
     *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *
     */

    /**
     * 获取团长数量
     * @param null $passingTime
     * @param null $shopId
     * @return int
     *
     * 说明：获取所有审核通过的团长，包括营业和歇业。
     */
    public function getTeamLeaderNum($passingTime = null, $shopId = null)
    {
        $teamLeaderNum = TeamLeaderModel::query()
            -> when($passingTime ?? 0, function ($query, $passingTime) {
                return $query->whereDate('passing_time', '<=', $passingTime. ' 23:59:59');
            })
            -> when($shopId ?? 0, function ($query, $shopId) {
                return $query->where('shop_id', '=', $shopId);
            })
            -> whereIn('status',[Stakeholder::LEADER_STATUS_IN_BUSINESS, Stakeholder::LEADER_STATUS_OUT_OF_BUSINESS])
            -> count();

        return $teamLeaderNum;
    }

    /**
     * 获取活跃团长数量
     * @param null $time
     * @param null $shopId
     * @return \Hyperf\Utils\HigherOrderTapProxy|mixed|void|null
     *
     * 说明：团长下只要有付过款的订单，就算是活跃团长
     */
    public function getActiveTeamLeaderNum($time = null, $shopId = null)
    {
        $res = OrderModel::query()
            ->selectRaw('
                COUNT(distinct(leader_id)) as leader_num
            ')
            -> when($shopId ?? 0, function ($query, $shopId) {
                return $query->where('shop_id', '=', $shopId);
            })
            ->whereDate('pay_at', '=', $time)
            ->where('is_pay', 1)
            ->where('platform_type', 2)
            ->value('leader_num');

        return $res;
    }

    /**
     * 获取某天所有团长下核销订单金额
     * @param null $time
     * @param null $shopId
     * @return string
     */
    public function orderWriteOffAmount($time = null, $shopId = null)
    {
        // 团长核销金额
        $res = OrderModel::query()
            ->selectRaw('
                order_no,
                SUM(total_price) as total_price
            ')
            -> when($shopId ?? 0, function ($query, $shopId) {
                return $query->where('shop_id', '=', $shopId);
            })
            ->whereDate('complete_date', '=',$time)
            ->where('write_off_code_status', 2)
            ->where('platform_type', 2)
            ->groupBy(['order_no'])
            ->pluck('total_price', 'order_no')->toArray();

        $orderIds = array_keys($res);
        // 查出每笔订单的退款
        $refundAmountByOrder = $this -> getRefundAmountByOrderIds($orderIds, $time);
        // 每笔订单核销金额减去退款金额
        foreach($res as $key => $val){
            if(array_key_exists($key,$refundAmountByOrder)){
                $res[$key] = bcsub((string)$val,(string)$refundAmountByOrder[$key],2);
            }
        }
        $result = sprintf("%.2f",array_sum($res));

        return $result;
    }

    /**
     * 退款查询
     * @param array $orderId
     * @param string|null $time
     * @return array
     *
     * 说明：客至退款 + 吾享退款
     */
    public function getRefundAmountByOrderIds(array $orderId, string $time = null)
    {
        // 查出每笔订单的退款
        $kzRefund = KzRefundLogModel::query()
            ->selectRaw("
                order_no,
                SUM(refund_balance_money) as refund_money
            ")
            -> where('platform_type', 2)
            -> whereIn('order_no', $orderId)
            -> when($time ?? 0, function ($query, $time) {
                return $query->whereDate('create_time', '=', $time);
            })
            -> groupBy(['order_no'])
            -> pluck('refund_money', 'order_no') -> toArray();

        $wxRefund = WxRefundLogModel::query()
            ->selectRaw("
                order_no,
                SUM(refund_wx_money) as refund_money
            ")
            -> where('platform_type', 2)
            -> whereIn('order_no', $orderId)
            -> when($time ?? 0, function ($query, $time) {
                return $query->whereDate('create_time', '=', $time);
            })
            -> groupBy(['order_no'])
            -> pluck('refund_money', 'order_no') -> toArray();

        return $refundAmountByOrder = $this -> arrayAdd($kzRefund, $wxRefund);
    }

    /**
     * 团长佣金合计
     * @param $time
     * @return float|mixed
     *
     * 说明：核销订单佣金 - 退款订单佣金
     */
    public function commissionOfTheLeader($time = null, $shopId = null)
    {
        $res = OrderModel::query()
            ->selectRaw('
                order_no,
                order_commission
            ')
            -> when($shopId ?? 0, function ($query, $shopId) {
                return $query->where('shop_id', '=', $shopId);
            })
            -> when($time ?? 0, function ($query, $time) {
                return $query->whereDate('complete_date', '=', $time);
            })
            ->where('platform_type', 2)
            ->where('write_off_code_status', 2)
            ->pluck('order_commission', 'order_no')->toArray();

        $orderIds = array_keys($res);

        // 查出每笔订单的退款佣金
        $kzRefund = KzRefundLogModel::query()
            ->selectRaw("
                order_no,
                SUM(refund_commission_money) as refund_money
            ")
            -> where('platform_type', 2)
            -> whereIn('order_no', $orderIds)
            -> when($time ?? 0, function ($query, $time) {
                return $query->whereDate('create_time', '=', $time);
            })
            -> groupBy(['order_no'])
            -> pluck('refund_money', 'order_no') -> toArray();

        $wxRefund = WxRefundLogModel::query()
            ->selectRaw("
                order_no,
                SUM(refund_commission_money) as refund_money
            ")
            -> where('platform_type', 2)
            -> whereIn('order_no', $orderIds)
            -> when($time ?? 0, function ($query, $time) {
                return $query->whereDate('create_time', '=', $time);
            })
            -> groupBy(['order_no'])
            -> pluck('refund_money', 'order_no') -> toArray();

        $refundAmountByOrder = $this -> arrayAdd($kzRefund, $wxRefund);
        // 每笔订单核销金额减去退款金额
        foreach($res as $key => $val){
            if(array_key_exists($key,$refundAmountByOrder)){
                $res[$key] = bcsub((string)$val,(string)$refundAmountByOrder[$key],2);
            }
        }
        $result = sprintf("%.2f",array_sum($res));

        return $result;
    }

    /**
     * 团长可提现佣金合计
     * @return string|null
     */
    public function withdrawableCommission($shopId = null)
    {
        $res = TeamLeaderModel::query()

            ->selectRaw('
                SUM(commission_amount) as total_commission_amount,
                SUM(frozen_amount) as total_frozen_amount
            ')
            ->when($shopId ?? 0, function ($query, $shopId) {
                return $query->where('shop_id', '=', $shopId);
            })
            ->whereIn('status', [3,4])
            ->first()->toArray();

        $balance = bcdiv((string)bcsub((string)$res['total_commission_amount'], (string)$res['total_frozen_amount'], 2), '100', 2);

        return $balance;
    }


    /**
     * 店铺下团长的冻结金额
     * @param null $shopId
     * @return string|null
     */
    public function frozenAmount($shopId = null)
    {
        $res = TeamLeaderModel::query()
            ->selectRaw('
                SUM(frozen_amount) as frozen_amount
            ')
            ->when($shopId ?? 0, function ($query, $shopId) {
                return $query->where('shop_id', '=', $shopId);
            })
            ->whereIn('status', [3,4])
            ->get()->toArray();

        $frozenAmount = bcdiv((string)$res[0]['frozen_amount'], '100', 2);

        return $frozenAmount;
    }

    /**
     * 团长提现中金额合计
     * @return string|null
     */
    public function commissionInWithdrawal()
    {
        $res = TeamLeaderCommissionRecord::query()
            ->selectRaw('
                SUM(expend) as expend
            ')
            ->where('type', 1)
            ->where('withdraw_status', 0)
            ->get()->toArray();
        $balancing = bcdiv((string)$res[0]['expend'], '100', 2);

        return $balancing;
    }

    /**
     * 以天为单位，获取一段时间范围内销售订单量和销售额
     * @return array
     *
     * 说明：订单数包含部分退的，不包含整单退。销售额应减去所有退款的金额
     */
    public function salesOrderTrend($shopId = null, $leaderId = null)
    {
        $nowTime = date('Y-m-d', time());
        $DaysAgo = date('Y-m-d', strtotime($nowTime . ' -29 day'));

        $dateArr = $this -> baseService -> prDates($DaysAgo, $nowTime);

        // 订单量，包含未退款的和部分退的订单

        // 未退款订单
        $count1 = OrderModel::query()
            ->selectRaw("DATE_FORMAT(pay_at, '%Y-%m-%d') as date,count(*) as sale_order")
            ->whereBetween('pay_at', [$DaysAgo.' 00:00:00', $nowTime.' 23:59:59'])
            ->where('is_pay', 1)
            ->where('platform_type', 2)
            ->where('refund_at', null)
            ->when($leaderId ?? 0, function ($query, $leaderId) {
                return $query->where('leader_id', '=', $leaderId);
            })
            ->when($shopId ?? 0, function ($query, $shopId) {
                return $query->where('shop_id', '=', $shopId);
            })
            ->groupBy(['date'])
            ->pluck('sale_order','date')->toArray();

        // 部分退款订单
        $count2 = OrderModel::query()
            ->selectRaw("DATE_FORMAT(pay_at, '%Y-%m-%d') as date,count(*) as sale_order")
            ->whereBetween('pay_at', [$DaysAgo.' 00:00:00', $nowTime.' 23:59:59'])
            ->where('is_pay', 1)
            ->where('platform_type', 2)
            ->where('is_whole', 1)
            ->when($leaderId ?? 0, function ($query, $leaderId) {
                return $query->where('leader_id', '=', $leaderId);
            })
            ->when($shopId ?? 0, function ($query, $shopId) {
                return $query->where('shop_id', '=', $shopId);
            })
            ->groupBy(['date'])
            ->pluck('sale_order','date')->toArray();

        $count = $this -> arrayAdd($count1,$count2);

//        var_dump($count);die;

        // 订单金额
        $selectRaw = "DATE_FORMAT(pay_at, '%Y-%m-%d') as date,SUM(total_price) as total_price,leader_id,shop_id";
        $res = OrderModel::query()
            ->selectRaw($selectRaw)
            ->whereBetween('pay_at', [$DaysAgo.' 00:00:00', $nowTime.' 23:59:59'])
            ->where('is_pay', 1)
            ->where('platform_type', 2)
//            ->whereIn('status', [2, 3, 4, 5])
            ->when($leaderId ?? 0, function ($query, $leaderId) {
                return $query->where('leader_id', '=', $leaderId);
            })
            ->when($shopId ?? 0, function ($query, $shopId) {
                return $query->where('shop_id', '=', $shopId);
            })
            ->groupBy(['date'])
            ->get()->toArray();

        // 销售额减去退款
        $refundAmountPerDay = $this -> getAmountOfRefundMoneyPerDay([$DaysAgo.' 00:00:00', $nowTime.' 23:59:59'],$leaderId ?? null, $shopId ?? null);
        $data = array_column($res ?? [], null, 'date');

        $list = [];
        foreach($dateArr as $key => $val){
            $list[$key]['date'] = $val;
            $list[$key]['sale_order'] = $data[$val]['sale_order'] ?? 0;
            if(array_key_exists($val, $refundAmountPerDay)){
                $list[$key]['total_price'] = bcsub((string)$data[$val]['total_price'] ?? '0.00', (string)$refundAmountPerDay[$val], 2);
            }else{
                $list[$key]['total_price'] = $data[$val]['total_price'] ?? '0.00';
            }
            if(array_key_exists($val, $count)){
                $list[$key]['sale_order'] = $count[$val];
            }else{
                $list[$key]['sale_order'] = 0;
            }
        }

        return ['code' => ErrorCode::SUCCESS, 'data' => $list];
    }

    /**
     * 团长销售额排名 TOP 20
     * @return array
     *
     * 说明：查销售额，只需 is_pay=1,再减去退款订单金额即可
     */
    public function leaderSalesRanking()
    {
        $res = TeamLeaderModel::query()
            ->from('hf_team_leader as t')
            ->leftJoin('store_order as o', 't.id', '=', 'o.leader_id')
            ->selectRaw('
                t.name,
                SUM(o.total_price) as total_price,
                o.leader_id
            ')
            ->where('is_pay', 1)
            ->where('platform_type', 2)
            ->groupBy(['leader_id'])
            ->limit(20)
            ->get();

        $leaderIdss = array_column($res->toArray() ?? [], 'leader_id');
        // 查询订单退款
        $leaderRefundMoney = $this -> getAmountOfRefundMoneyByLeader($leaderIdss);
        foreach($res as $key => $val){
            if(array_key_exists($val['leader_id'], $leaderRefundMoney)){
                $res[$key]['total_price'] = bcsub((string)$val['total_price'],(string)$leaderRefundMoney[$val['leader_id']], 2);
                if($res[$key]['total_price'] <= '0.00'){
                    unset($res[$key]);
                }
            }
        }

        // 对数组重新排序
        $resArr = $this -> arrFunction -> arraySort( $res->toArray(), 'total_price');
        $resArr = array_values($resArr);
        foreach($resArr as $k => $v){
            $resArr[$k]['rank_id'] = $k + 1;
        }

        return ['code' => ErrorCode::SUCCESS, 'data' => $resArr];
    }

    // 通过一个时间段，算出每天的退款总金额
    public function getAmountOfRefundMoneyPerDay(array $date, $leaderId = null, $shopId = null)
    {
        $kzRefund = KzRefundLogModel::query()
            ->selectRaw("
                DATE_FORMAT(create_time, '%Y-%m-%d') as time,
                SUM(refund_balance_money) as refund_money
            ")
            -> where('platform_type', 2)
            -> when($leaderId ?? 0, function ($query, $leaderId) {
                return $query->where('leader_id', '=', $leaderId);
            })
            -> when($shopId ?? 0, function ($query, $shopId) {
                return $query->where('shop_id', '=', $shopId);
            })
            -> whereBetween('create_time', $date)
            -> groupBy(['time'])
            -> pluck('refund_money', 'time') -> toArray();

        $wxRefund = WxRefundLogModel::query()
            ->selectRaw("
                DATE_FORMAT(create_time, '%Y-%m-%d') as time,
                SUM(refund_wx_money) as refund_money
            ")
            -> where('platform_type', 2)
            -> when($leaderId ?? 0, function ($query, $leaderId) {
                return $query->where('leader_id', '=', $leaderId);
            })
            -> when($shopId ?? 0, function ($query, $shopId) {
                return $query->where('shop_id', '=', $shopId);
            })
            -> whereBetween('create_time', $date)
            -> groupBy(['time'])
            -> pluck('refund_money', 'time') -> toArray();

        $res = $this -> arrayAdd($kzRefund, $wxRefund);

        return $res;
    }

    /**
     * 获取团长所有的退款金额，可查询多个团长
     * @param array $leaders
     * @return array
     */
    public function getAmountOfRefundMoneyByLeader(array $leaders)
    {
        $kzRefund = KzRefundLogModel::query()
            ->selectRaw('
                leader_id,
                SUM(refund_balance_money) as kz_refund_money
            ')
            -> whereIn('leader_id', $leaders)
            -> where('platform_type', 2)
            -> groupBy(['leader_id'])
            -> pluck('kz_refund_money', 'leader_id') -> toArray();

        // 查询客至订单退款，有退款则需要从销售额扣除
        $wxRefund = WxRefundLogModel::query()
            ->selectRaw('
                leader_id,
                SUM(refund_wx_money) as wx_refund_money
            ')
            -> whereIn('leader_id', $leaders)
            -> where('platform_type', 2)
            -> groupBy(['leader_id'])
            -> pluck('wx_refund_money', 'leader_id') -> toArray();

        $leaderRefundMoney = $this -> arrayAdd($kzRefund, $wxRefund);

        return $leaderRefundMoney;
    }

    public function getAmountOfRefundMoneyByOrderNo(array $orderNo)
    {
        $kzRefund = KzRefundLogModel::query()
            ->selectRaw('
                order_no,
                SUM(refund_balance_money) as kz_refund_money
            ')
            -> whereIn('order_no', $orderNo)
            -> where('platform_type', 2)
            -> groupBy(['order_no'])
            -> pluck('kz_refund_money', 'order_no') -> toArray();

        // 查询客至订单退款，有退款则需要从销售额扣除
        $wxRefund = WxRefundLogModel::query()
            ->selectRaw('
                order_no,
                SUM(refund_wx_money) as wx_refund_money
            ')
            -> whereIn('order_no', $orderNo)
            -> where('platform_type', 2)
            -> groupBy(['order_no'])
            -> pluck('wx_refund_money', 'order_no') -> toArray();

        $leaderRefundMoney = $this -> arrayAdd($kzRefund, $wxRefund);

        return $leaderRefundMoney;
    }

    /**
     * 销售商品排名 TOP 20
     * @return array
     */
    public function commoditySalesRanking()
    {
        $res = OrderGoodsModel::query()
            ->selectRaw('
                goods_id,
                goods_title as title,
                SUM(number) as number,
                SUM(dis_price) as sales_volume
            ')
            ->whereHas('order', function ($q) {
                $q->where('is_pay', 1);
                $q->where('platform_type', 2);
            })
            ->having('number', '>', 0)
            ->groupBy(['goods_id'])
            ->orderBy('number', 'desc')
            ->orderBy('sales_volume', 'desc')
            ->limit(20)
            ->get();

        foreach($res as $key => $val){
            $res[$key]['rank_id'] = $key + 1;
        }

        return ['code' => ErrorCode::SUCCESS, 'data' => $res];
    }

    /**
     * 店铺数据报表
     * @param $params
     * @return array
     *
     * 说明：精确到某天
     */
    public function storeDataReport($params)
    {
        $time = $params['date'] ?? date('Y-m-d', time());
        $endTimestamp = strtotime(date('Y-m-d', time())) + 86399;
        if(strtotime($time) > $endTimestamp){
            return ['code' => ErrorCode::SUCCESS, 'data' => []];
        }

        if (!empty($params['shop_id'])) {
            $params['shop_id'] = [$params['shop_id']];
        } elseif (!empty($params['shop_group_id'])) {
            $shops = ShopModel::query()->where(['shop_group_id' => $params['shop_group_id']])->pluck('shop_id')->toArray();
            $shops = !empty($shops) ? $shops : ['-1'];
            $params['shop_id'] = $shops;
        }

        // 查询出所有店铺
        $shopsInfo = ShopModel::query()
            -> select(['shop_id', 'shop_name', 'shop_group_id'])
            -> where(['is_deleted' => 0])
            -> when($params['shop_id'] ?? 0, function ($query, $shop_id) {
                return $query->whereIn('shop_id', $shop_id);
            })
            -> get() -> toArray();

        $shopGroupIds = array_column($shopsInfo, 'shop_group_id');

        // 获取店群
        $shopGroupnames = ShopGroupModel::query()
            -> where('deleted_at', null)
            -> whereIn('id',$shopGroupIds)
            -> pluck('shop_group_name', 'id');

        // 每个店铺的团长数量
        $teamLeaderNum = $this -> getLeaderNumPerShop($time);
        //每个店铺团长待核销订单数量
        $toBeWrittenOff = $this -> getLeadertoBeWrittenOffOrder($time);
        //每个店铺团长已核销订单数量
        $writtenOff = $this -> getLeaderWrittenOffOrder($time);
        //每个店铺团长核销订单金额
        $cancellationOfOrderAmountByTeamLeader = $this -> getCancellationOfOrderAmountByTeamLeader($time);
        //每个店铺团长退款订单数
        $numberOfRefundOrders = $this -> getNumberOfRefundOrders($time);
        //每个店铺团长退款金额
        $kzRefundAmount = $this -> getKzRefundAmount($time);
        $wxRefundAmount = $this -> getWxRefundAmount($time);
        $totalRefundAmount = $this -> arrayAdd($kzRefundAmount, $wxRefundAmount);
        //每个店铺团长退款佣金
        $refundCommission = $this -> refundCommission($time);
        //每个店铺团长待结算佣金
        $commissionToBeSettled = $this -> commissionToBeSettled();
        //每个店铺团长提现中佣金
        $commissionInWithdrawal = $this -> getCommissionInWithdrawal($time);
        // 团长可提现佣金
        $leaderWithdrawableCommission = $this -> leaderWithdrawableCommission();
        // 团长佣金合计
        $leaderCommissionTotal = $this -> commissionOfTheLeader($time);

        foreach($shopsInfo as $key => $val){
            $shopsInfo[$key]['date'] = $time;
            $shopsInfo[$key]['shop_group_name'] = $shopGroupnames[$val['shop_group_id']];
            $shopsInfo[$key]['leader_num'] = $teamLeaderNum[$val['shop_id']] ?? 0;
            $shopsInfo[$key]['order_to_be_sorted'] = 0;
            $shopsInfo[$key]['to_be_written_off_num'] = $toBeWrittenOff[$val['shop_id']] ?? 0;
            $shopsInfo[$key]['written_off_num'] = $writtenOff[$val['shop_id']] ?? 0;
            $shopsInfo[$key]['cancellation_of_order_amount'] = $cancellationOfOrderAmountByTeamLeader[$val['shop_id']] ?? 0;
            $shopsInfo[$key]['number_of_refund_orders'] = $numberOfRefundOrders[$val['shop_id']] ?? 0;
            $shopsInfo[$key]['refund_amount'] = $totalRefundAmount[$val['shop_id']] ?? '0.00';
            $shopsInfo[$key]['refund_commission'] = $refundCommission[$val['shop_id']] ?? '0.00';
            $shopsInfo[$key]['commission_to_be_settled'] = $commissionToBeSettled[$val['shop_id']] ?? '0.00';   // 待结算佣金
            $shopsInfo[$key]['commission_in_withdrawal'] = $commissionInWithdrawal[$val['shop_id']] ?? '0.00';  // 提现中佣金
            $shopsInfo[$key]['leader_withdrawable_commission'] = $leaderWithdrawableCommission[$val['shop_id']] ?? '0.00';   // 可提现佣金
            $shopsInfo[$key]['leader_total_commission'] = $this -> commissionOfTheLeader($time, $val['shop_id']);   // 团长佣金合计 = 待结算佣金+提现中佣金+团长可提现佣金=团长佣金合计
        }

        return ['code' => ErrorCode::SUCCESS, 'data' => $shopsInfo];

    }

    /**
     * 截止到某天，每个店铺下团长数量
     * @param null $time
     * @param null $realTime    默认 false 为店铺数据报表（某一天），为 true 时：店铺实时数据（总数居）
     *
     * @return array
     */
    public function getLeaderNumPerShop($time = null, $realTime = false)
    {
        $choiceTime = null;
        if($realTime == false){
            $choiceTime = $time ? $time : Carbon::today() -> toDateString();
        }

        $teamLeaderNum = TeamLeaderModel::query()
            -> selectRaw('
                shop_id,
                COUNT(id) as leader_num
            ')
            -> whereIn('status', [3,4])
            -> when($choiceTime ?? 0, function ($query, $choiceTime) {
                return $query->where('passing_time', '<=', $choiceTime. ' 23:59:59');
            })
            -> groupBy(['shop_id'])
            -> pluck('leader_num', 'shop_id') -> toArray();

        return $teamLeaderNum;
    }

    /**
     * 获取每个店铺下团长待核销订单数量
     * @param null $time
     * @param false $realTime   默认 false 为店铺数据报表（某一天），为 true 时：店铺实时数据（总数居）
     * @return array
     */
    public function getLeadertoBeWrittenOffOrder($time = null, $realTime = false)
    {
        $choiceTime = null;
        if($realTime == false){
            $choiceTime = $time ? $time : Carbon::today() -> toDateString();
        }

        $toBeWrittenOffOrderNum = OrderModel::query()
            -> selectRaw('
                shop_id,
                COUNT(order_no) as order_num
            ')
            -> whereIn('status', [2,3])
            -> when($choiceTime ?? 0, function ($query, $choiceTime) {
                return $query->where('pay_at', '<=', $choiceTime. ' 23:59:59');
            })
            -> where([
                ['platform_type', '=', 2]
            ])
            -> groupBy(['shop_id'])
            -> pluck('order_num', 'shop_id') -> toArray();

        return $toBeWrittenOffOrderNum;
    }

    /**
     * 获取每个店铺下团长已核销订单数量
     * @param $time
     * @return array
     */
    public function getLeaderWrittenOffOrder($time = null, $realTime = false)
    {
        $choiceTime = null;
        if($realTime == false){
            $choiceTime = $time ? $time : Carbon::today() -> toDateString();
        }

        // 每个店铺已核销未退款订单量
        $noRefundOrderNum = OrderModel::query()
            -> selectRaw('
                shop_id,
                COUNT(order_no) as order_num
            ')
            -> where('write_off_code_status', 2)
            -> where('refund_at', null)
            -> when($choiceTime ?? 0, function ($query, $choiceTime) {
                return $query->whereDate('complete_date', '=', $choiceTime);
            })
            -> where([
                ['platform_type', '=', 2]
            ])
            -> groupBy(['shop_id'])
            -> pluck('order_num', 'shop_id') -> toArray();

        // 每个店铺下已核销整单退订单量
        $partRefundOrderNum = OrderModel::query()
            -> selectRaw('
                shop_id,
                COUNT(order_no) as order_num
            ')
            -> where('write_off_code_status', 2)
            -> when($choiceTime ?? 0, function ($query, $choiceTime) {
                return $query->whereDate('complete_date', '=', $choiceTime);
            })
            -> where([
                ['platform_type', '=', 2],
                ['is_pay', '=', 1],
                ['is_whole', '=', 1]
            ])
            -> groupBy(['shop_id'])
            -> pluck('order_num', 'shop_id') -> toArray();
        $count = $this -> arrayAdd($noRefundOrderNum,$partRefundOrderNum);

        return $count;
    }

    /**
     * 每个店铺下已核销订单金额
     * @param null $time
     * @param false $realTime   默认 false 为店铺数据报表（某一天），为 true 时：店铺实时数据（总数居）
     * @return array
     *
     * 说明：获取已核销总额后，需要减去退款订单核销金额
     */
    public function getCancellationOfOrderAmountByTeamLeader($time = null, $realTime = false)
    {
        $choiceTime = null;
        if($realTime == false){
            $choiceTime = $time ? $time : Carbon::today() -> toDateString();
        }

        // 目前包含未核销直接退款，需过滤。。。退款多退了

        // 所有已核销的团长订单列表
        $WrittenOffOrderNum = OrderModel::query()
            -> selectRaw('
                order_no,
                shop_id,
                SUM(total_price) as total_price
            ')
            -> when($choiceTime ?? 0, function ($query, $choiceTime) {
                return $query->whereDate('complete_date', '=', $choiceTime);
            })
            -> where([
                ['platform_type', '=', 2],
                ['write_off_code_status', '=', 2]
            ])
            -> groupBy(['order_no'])
            -> get() -> toArray();

        $orderNos = array_column($WrittenOffOrderNum,'order_no');
        $orders = array_column($WrittenOffOrderNum, null, 'order_no');

        // 获取订单所有退款金额，不能用 shop_id 进行查询，因为只需要获取已核销的订单，要用 order_no
        $kzRefund = KzRefundLogModel::query() ->selectRaw("
                order_no,
                SUM(refund_balance_money) as refund_money
            ")
            -> whereIn('order_no',$orderNos)
            -> when($choiceTime ?? 0, function ($query, $choiceTime) {
                return $query->whereDate('create_time', '=', $choiceTime);
            })
            -> groupBy(['order_no'])
            -> pluck('refund_money','order_no') -> toArray();

        $wxRefund = WxRefundLogModel::query() ->selectRaw("
                order_no,
                SUM(refund_wx_money) as refund_money
            ")
            -> whereIn('order_no',$orderNos)
            -> when($choiceTime ?? 0, function ($query, $choiceTime) {
                return $query->whereDate('create_time', '=', $choiceTime);
            })
            -> groupBy(['order_no'])
            -> pluck('refund_money','order_no') -> toArray();
        $refund = $this -> arrayAdd($kzRefund, $wxRefund);

        // 核销金额减去退款金额
        foreach($orders as $key => $val){
            if(array_key_exists($key,$refund)){
                $orders[$key]['total_price'] = bcsub((string)$val['total_price'],(string)$refund[$key],2);
            }
        }
        $res = $this -> arrFunction -> addValByOtherVal($orders, 'shop_id', 'total_price');

        return $res;
    }

    /**
     * 团长退款订单数
     * @param $time
     * @return array
     *
     * 说明：所有的退款订单数只包含整单退
     */
    public function getNumberOfRefundOrders($time = null, $realTime = false)
    {
        $choiceTime = null;
        if($realTime == false){
            $choiceTime = $time ? $time : Carbon::today() -> toDateString();
        }

        $WrittenOffOrderNum = OrderModel::query()
            -> selectRaw('
                shop_id,
                COUNT(*) as refund_order_num
            ')
            -> when($choiceTime ?? 0, function ($query, $choiceTime) {
                return $query->whereDate('refund_at', '=', $choiceTime);
            })
            ->where(function ($query) use ($choiceTime) {
                $query->where('platform_type', '=', 2)
                    ->where('status', '=', 5);
//                    ->orWhere('is_whole', '=', 1);  //  部分退
            })
            -> groupBy(['shop_id'])
            -> pluck('refund_order_num', 'shop_id') -> toArray();

        return $WrittenOffOrderNum;
    }

    /**
     * 团长客至退款金额
     * @param $time
     */
    public function getKzRefundAmount($time = null, $realTime = false)
    {
        $choiceTime = null;
        if($realTime == false){
            $choiceTime = $time ? $time : Carbon::today() -> toDateString();
        }

        $res = KzRefundLogModel::query()
            ->selectRaw('
                shop_id,
                SUM(refund_balance_money) as refund_balance_money
            ')
            -> when($choiceTime ?? 0, function ($query, $choiceTime) {
                return $query->whereDate('create_time', '=', $choiceTime);
            })
            ->where('platform_type', 2)
//            ->whereDate('create_time', $choiceTime)
            ->groupBy(['shop_id'])
            ->pluck('refund_balance_money', 'shop_id')->toArray();

        return $res;

    }

    /**
     * 团长吾享退款金额
     * @param $time
     */
    public function getWxRefundAmount($time = null, $realTime = false)
    {
        $choiceTime = null;
        if($realTime == false){
            $choiceTime = $time ? $time : Carbon::today() -> toDateString();
        }

        $res = WxRefundLogModel::query()
            ->selectRaw('
                shop_id,
                SUM(refund_wx_money) as refund_wx_money
            ')
            -> when($choiceTime ?? 0, function ($query, $choiceTime) {
                return $query->whereDate('create_time', '=', $choiceTime);
            })
            ->where('platform_type', 2)
//            ->whereDate('create_time', $choiceTime)
            ->groupBy(['shop_id'])
            ->pluck('refund_wx_money', 'shop_id')->toArray();

        return $res;

    }

    /**
     * 两个数组相加，相同键名，键值相加。键名不同，保留键值
     * @param array $arr1
     * @param array $arr2
     */
    public function arrayAdd(array $arr1 = [],array $arr2 = [])
    {
        $arr3 = $arr1 + $arr2;
        $arr4 = array_intersect_key($arr2, $arr1);
        foreach($arr4 as $k => $v) {
            $arr3[$k] += $v;
        }
        return $arr3;
    }

    /**
     * 每个店铺下团长所有的退款退佣金
     * @param $time
     * @return array
     */
    public function refundCommission($time = null, $realTime = false)
    {
        $choiceTime = null;
        if($realTime == false){
            $choiceTime = $time ? $time : Carbon::today() -> toDateString();
        }

        // 查出每位团长的总退款退佣金金额及关联店铺编号
//        $refundCommissionPerLeader = TeamLeaderCommissionRecord::query()
//            ->selectRaw('
//                shop_id,
//                (CONVERT(SUM(expend) / 100,DECIMAL(10,2))) as expend
//            ')
//            -> when($choiceTime ?? 0, function ($query, $choiceTime) {
//                return $query->whereDate('created_at', '=', $choiceTime);
//            })
//            ->where('type', 3)
//            ->groupBy(['shop_id'])
//            ->get()->toArray();

        // 相同店铺退佣金金额相加
//        $item = [];
//        foreach($refundCommissionPerLeader as $k => $v){
//            if (!isset($item[$v['shop_id']])) {
//                $item[$v['shop_id']] = $v['expend'];
//            } else {
//                $item[$v['shop_id']] += $v['expend'];
//            }
//        }

//        return $item;

        $kzRefund = KzRefundLogModel::query() ->selectRaw("
                shop_id,
                SUM(refund_commission_money) as refund_money
            ")
            -> when($choiceTime ?? 0, function ($query, $choiceTime) {
                return $query->whereDate('create_time', '=', $choiceTime);
            })
            -> groupBy(['shop_id'])
            -> pluck('refund_money','shop_id') -> toArray();

        $wxRefund = WxRefundLogModel::query() ->selectRaw("
                shop_id,
                SUM(refund_commission_money) as refund_money
            ")
            -> when($choiceTime ?? 0, function ($query, $choiceTime) {
                return $query->whereDate('create_time', '=', $choiceTime);
            })
            -> groupBy(['shop_id'])
            -> pluck('refund_money','shop_id') -> toArray();

        $refund = $this -> arrayAdd($kzRefund,$wxRefund);

        return $refund;
    }

    /**
     * 团长待结算佣金
     * @return array
     * 说明：团长冻结金额 + 申请退款被冻结金额
     */
    public function commissionToBeSettled()
    {
        // 团长现在往前48小时的所有佣金
//        $commission = OrderModel::query()
//            ->selectRaw("
//                shop_id,
//                SUM(total_price) as total_price
//            ")
//            ->where('platform_type', 2)
//            ->where()

        $res = TeamLeaderModel::query()
            ->selectRaw('
                shop_id,
                (CONVERT(SUM(frozen_amount) / 100,DECIMAL(10,2))) as frozen_amount
            ')
            ->whereIn('status', [3, 4])
            ->groupBy(['shop_id'])
            ->pluck('frozen_amount', 'shop_id')->toArray();

        return $res;
    }

    /**
     * 获取店铺下某一天所有团长提现中的佣金
     * @param $time
     * @return array
     */
    public function getCommissionInWithdrawal($time = null, $realTime = false)
    {
        $choiceTime = null;
        if($realTime == false){
            $choiceTime = $time ? $time : Carbon::today() -> toDateString();
        }

        $refundCommissionPerLeader = TeamLeaderCommissionRecord::query()
            ->selectRaw('
                shop_id,
                (CONVERT(SUM(expend) / 100,DECIMAL(10,2))) as expend
            ')
            -> when($choiceTime ?? 0, function ($query, $choiceTime) {
                return $query->whereDate('created_at', '=', $choiceTime);
            })
            ->where('type', 1)
            ->where('withdraw_status',0)
            ->groupBy(['leader_id'])
            ->get()->toArray();

        // 相同店铺退佣金金额相加
        $item = [];
        foreach($refundCommissionPerLeader as $k => $v){
            if (!isset($item[$v['shop_id']])) {
                $item[$v['shop_id']] = $v['expend'];
            } else {
                $item[$v['shop_id']] += $v['expend'];
            }
        }

        return $item;
    }

    /**
     * 团长可提现佣金
     * @return array
     */
    public function leaderWithdrawableCommission()
    {
        $res = TeamLeaderModel::query()
            ->selectRaw('
                shop_id,
                (CONVERT((SUM(commission_amount) - SUM(frozen_amount)) / 100,DECIMAL(10,2))) as commission
            ')
            ->whereIn('status', [3,4])
            ->groupBy(['shop_id'])
            ->pluck('commission', 'shop_id')->toArray();

        $shopIds = array_keys($res);
        $leaderInShop = TeamLeaderModel::query()
            ->whereIn('shop_id', $shopIds)
            ->get(['id','shop_id']);

        $item = [];
        foreach ($leaderInShop as $k => $v){
//            if(!$item[$v->shop_id]){
            if(!isset($item[$v->shop_id])){
                $item[$v->shop_id] = (string)$v->id;
            }else{
                $item[$v->shop_id] .= ','.$v->id;
            }
        }
        $map = [];
        foreach($item as $k => $v){
            $map[$k] = $this -> getFreezeOrderCommission($v);
            if($map[$k] > 0){
                $map[$k] = bcdiv((string)$map[$k], '100', 2);
            }
        }
        foreach ($res as $k => $v){
            $res[$k] = bcsub((string)$v, (string)$map[$k],2);
        }

        return $res;
    }

    /**
     * 获取团长配送单列表
     * @param int $leader_id
     * @param int $status
     * @return array
     */
    public function deliverList(int $leader_id, int $status)
    {
        $teamleaderArr = $this->teamLeaderByShop(['id'=>$leader_id], ['name', 'id', 'shop_id', 'delivery_address', 'detail_address','phone','mid']);
        if(empty($teamleaderArr)){
            return $teamleaderArr;
        }
        $teamleader = $teamleaderArr[0];
        $data = [
            'name' => $teamleader['name'],
            'delivery_address' => $teamleader['delivery_address'] . $teamleader['detail_address'],
            'leader_logo' => $teamleader['member']['face_url'],
            'phone' => $teamleader['phone'],
        ];
        $sart = LeaderSorting::query()->from('hf_leader_sorting as h')
            ->join('store_goods as g','h.goods_id','=','g.id')
            ->where(['h.leader_id' => $leader_id])
            ->select('h.goods_id','h.num','h.sorting_time','h.status','h.sorting_num','g.logo')
            ->groupBy(['h.goods_id','h.sorting_time'])
            ->orderBy('h.sorting_time','desc')
            ->get()
            ->toArray();
        $arr = [];
        foreach ($sart as $v){
            $arr[$v['sorting_time']][] =$v;
        }
        $ars = [];
        foreach ($arr as $time => $v){
            $order_num = array_sum(array_column($v,'num'));
            $sorting_num = array_sum(array_column($v,'sorting_num'));
            $num = $order_num - $sorting_num;
            $sorting_status = $num == 0 ? '已分拣' : '待分拣';
            if ($status == 1 && $sorting_status != '已分拣') {
                continue;
            }
            if ($status == 2 && $sorting_status != '待分拣') {
                continue;
            }
            $_ars['time'] = $time;
            $_ars['number'] = $order_num;
            $_ars['sort_name'] = $sorting_status;
            $_ars['list'] = $v;
            $ars[] = $_ars;
        }
        return [
            'code' => ErrorCode::SUCCESS,
            'data' => [
                'title' => $data,
                'list' => $ars,
            ],
        ];
    }

    /**
     * 获取团长配送单详情
     * @param int $leader_id
     * @param string $times
     * @return array|string
     */
    public function deliverDetails(int $leader_id,string $times )
    {
        $sart = LeaderSorting::query()->from('hf_leader_sorting as h')
            ->join('store_goods as g','h.goods_id','=','g.id')
            ->where(['h.leader_id' => $leader_id,'h.sorting_time' => $times])
            ->select('h.goods_id','h.num','h.sorting_time','h.status','h.sorting_num','g.logo','g.title')
            ->groupBy(['h.goods_id'])
            ->get()
            ->toArray();
        $num =  array_sum(array_column($sart,'num'));
        $sortingNum = array_sum(array_column($sart,'sorting_num'));
        $res = LeaderSortingLog::query()
            ->where(['leader_id' => $leader_id,'sorting_time' => $times])
            ->select('created_at')
            ->get()
            ->toArray();
        $sortingTimes = array_values(array_unique(array_column($res,'created_at')));
        $arr = [];
        $arr['time'] = $times;
        if(empty($sortingNum)){
            $arr['sorting_status'] = '待分拣';
        }else{
            if($num>$sortingNum){
                $arr['sorting_status'] = '部分分拣';
            }else{
                $arr['sorting_status'] = '已分拣';
            }
        }
        $arr['sorting_time'] = $sortingTimes;
        $arr['goods'] = [];
        foreach ($sart as $k =>$v){
            $need_sorting_num = $sart[$k]['num'] - $sart[$k]['sorting_num'];
            $sart[$k]['need_sorting_num'] = $need_sorting_num>0?$need_sorting_num:0;
            $arr['goods'][] = $sart[$k];
        }
        return $arr;
    }

    /**
     * 店铺数据报表详情 -- 团长订单
     * @param array $params
     * @param int $perPage
     * @param string[] $field
     * @return array
     */
    public function storeDataReportDetailsWithOrder($params = [], $perPage = 15, $field = ['*'])
    {
        if (!empty($params['shop_id'])) {
            $params['shop_id'] = [$params['shop_id']];
        } elseif (!empty($params['shop_group_id'])) {
            $shops = ShopModel::query()->where(['shop_group_id' => $params['shop_group_id']])->pluck('shop_id')->toArray();
            $shops = !empty($shops) ? $shops : ['-1'];
            $params['shop_id'] = $shops;
        } else {
            $params['shop_id'] = ['-1'];
        }

        $order = OrderModel::query()
            ->from('store_order as o')
            ->leftJoin('store_order_refund as or', 'o.order_no', '=', 'or.order_no')
            ->leftJoin('hf_team_leader as t', 't.id', '=', 'o.leader_id')
            ->selectRaw('
                o.order_no,
                o.total_price,
                o.order_commission,
                or.refund_money,
                o.status,
                o.pay_at,
                o.complete_date,
                t.name,
                t.delivery_address,
                t.detail_address,
                t.phone,
                t.status as leader_status,
                o.shop_id,
                o.order_goods_num,
                o.is_whole
            ')
            ->whereIn('o.shop_id', $params['shop_id'])
            ->where('o.platform_type', 2)
            ->when($params['date'] ?? 0, function ($query, $date) {
                return $query->whereDate('o.create_at', '=', $date);
            })
            ->when($params['order_no'] ?? 0, function ($query, $orderNo) {
                return $query->where('o.order_no', '=', $orderNo);
            })
            ->when($params['leader_id'] ?? 0, function ($query, $leaderId) {
                return $query->where('t.id', '=', $leaderId);
            })
            ->when($params['phone'] ?? 0, function ($query, $phone) {
                return $query->where('t.phone', '=', $phone);
            })
            ->when($params['leader_status'] ?? 0, function ($query, $leaderStatus) {
                return $query->where('t.status', '=', $leaderStatus);
            })
            ->latest('o.create_at')
            ->paginate($perPage);

        $orderArr = $order->toArray()['data'];
        $orderIds = array_column($orderArr,'order_no');
        $orderGoods = OrderGoodsModel::query()
            ->select(['order_no','goods_title'])
            ->whereIn('order_no',$orderIds)
            ->groupBy(['order_no'])
            ->pluck('goods_title','order_no')->toArray();

        foreach ($order as $key => $val){
            $order[$key]['order_goods'] = $orderGoods[$val -> order_no] ? $orderGoods[$val -> order_no].' 等商品' : '';
        }

        return ['code' => ErrorCode::SUCCESS, 'data' => $order];
    }

    /**
     * 店铺数据报表详情 -- 团长提现记录
     * @param array $params
     * @param int $perPage
     * @param string[] $field
     * @return array
     */
    public function storeDataReportDetailsWithWithdrawal($params = [], $perPage = 15, $field = ['*'])
    {
        if (!empty($params['shop_id'])) {
            $params['shop_id'] = [$params['shop_id']];
        } elseif (!empty($params['shop_group_id'])) {
            $shops = ShopModel::query()->where(['shop_group_id' => $params['shop_group_id']])->pluck('shop_id')->toArray();
            $shops = !empty($shops) ? $shops : ['-1'];
            $params['shop_id'] = $shops;
        } else {
            $params['shop_id'] = ['-1'];
        }

        $query = TeamLeaderCommissionRecord::query();
        if (in_array($params['withdraw_status'], ['0', '1'])) {
            $query->where('tr.withdraw_status', '=', $params['withdraw_status']);
        }
        // 筛选处店铺下所有的团长
        $res = $query
            ->from('hf_team_leader_commission_record as tr')
            ->leftJoin('hf_team_leader as t', 't.id', '=', 'tr.leader_id')
            ->selectRaw('
                tr.id,
                t.name,
                tr.serial_no,
                tr.created_at,
                tr.withdraw_time,
                t.account_name,
                t.account_bank,
                t.bank_card_number,
                (CONVERT(tr.expend / 100,DECIMAL(10,2))) as expend,
                tr.withdraw_status
            ')
            ->where('tr.type',1)
            ->whereIn('t.shop_id', $params['shop_id'])
            ->when($params['date'] ?? 0, function ($query, $date) {
                return $query->whereDate('tr.created_at', '=', $date);
            })
            ->when($params['serial_no'] ?? 0, function ($query, $serialNo) {
                return $query->where('tr.serial_no', '=', $serialNo);
            })
            ->latest('tr.created_at')
            ->paginate($perPage);

        if (!$res->isEmpty()) {
            $bankName = $this->getBankList();
            foreach ($res as $key => $val) {
                $val->account_bank = $bankName[$val->account_bank]['name'] ?? '未知';
            }
        }

        return ['code' => ErrorCode::SUCCESS, 'data' => $res];
    }


    /**
     * 团长 Web--获取店铺实时数据
     * @param array $params
     *
     * @return array
     */
    public function getStoreRealTimeData(array $params)
    {
        if (!empty($params['shop_id'])) {
            $params['shop_id'] = [$params['shop_id']];
        } elseif (!empty($params['shop_group_id'])) {
            $shops = ShopModel::query()->where(['shop_group_id' => $params['shop_group_id']])->pluck('shop_id')->toArray();
            $shops = !empty($shops) ? $shops : ['-1'];
            $params['shop_id'] = $shops;
        }

        // 查询出所有店铺
        $shopsInfo = ShopModel::query()
            -> select(['shop_id', 'shop_name', 'shop_group_id'])
            -> where(['is_deleted' => 0])
            -> when($params['shop_id'] ?? 0, function ($query, $shop_id) {
                return $query->whereIn('shop_id', $shop_id);
            })
            -> get() -> toArray();
        $shopGroupIds = array_column($shopsInfo, 'shop_group_id');
        // 获取店群
        $shopGroupnames = ShopGroupModel::query()
            -> where('deleted_at', null)
            -> whereIn('id',$shopGroupIds)
            -> pluck('shop_group_name', 'id');

        // 每个店铺的团长数量
        $teamLeaderNum = $this -> getLeaderNumPerShop(null,true);
        //每个店铺团长待核销订单数量
        $toBeWrittenOff = $this -> getLeadertoBeWrittenOffOrder(null, true);
        //每个店铺活跃团长数量
        $activeLeader = $this -> getActiveLeaderInShop();
        //每个店铺团长已核销订单数量
        $writtenOff = $this -> getLeaderWrittenOffOrder(null, true);
        //每个店铺团长核销订单金额
        $cancellationOfOrderAmountByTeamLeader = $this -> getCancellationOfOrderAmountByTeamLeader(null, true);
        //每个店铺团长退款订单数
        $numberOfRefundOrders = $this -> getNumberOfRefundOrders(null, true);
        //每个店铺团长退款金额
        $kzRefundAmount = $this -> getKzRefundAmount(null, true);
        $wxRefundAmount = $this -> getWxRefundAmount(null, true);
        $totalRefundAmount = $this -> arrayAdd($kzRefundAmount, $wxRefundAmount);
        //每个店铺团长退款佣金
        $refundCommission = $this -> refundCommission(null, true);
        //每个店铺团长待结算佣金
        $commissionToBeSettled = $this -> commissionToBeSettled();
        //每个店铺团长提现中佣金
        $commissionInWithdrawal = $this -> getCommissionInWithdrawal(null, true);
        // 团长可提现佣金
        $leaderWithdrawableCommission = $this -> leaderWithdrawableCommission();

        foreach($shopsInfo as $key => $val){
            $shopsInfo[$key]['active_leader_num'] = $activeLeader[$val['shop_id']] ?? 0;
            $shopsInfo[$key]['shop_group_name'] = $shopGroupnames[$val['shop_group_id']];
            $shopsInfo[$key]['leader_num'] = $teamLeaderNum[$val['shop_id']] ?? 0;
            $shopsInfo[$key]['order_to_be_sorted'] = 0;
            $shopsInfo[$key]['to_be_written_off_num'] = $toBeWrittenOff[$val['shop_id']] ?? 0;
            $shopsInfo[$key]['written_off_num'] = $writtenOff[$val['shop_id']] ?? 0;
            $shopsInfo[$key]['cancellation_of_order_amount'] = $cancellationOfOrderAmountByTeamLeader[$val['shop_id']] ?? 0;
            $shopsInfo[$key]['number_of_refund_orders'] = $numberOfRefundOrders[$val['shop_id']] ?? 0;
            $shopsInfo[$key]['refund_amount'] = $totalRefundAmount[$val['shop_id']] ?? '0.00';
            $shopsInfo[$key]['refund_commission'] = $refundCommission[$val['shop_id']] ?? '0.00';
            $shopsInfo[$key]['commission_to_be_settled'] = $commissionToBeSettled[$val['shop_id']] ?? '0.00';   // 待结算佣金
            $shopsInfo[$key]['commission_in_withdrawal'] = $commissionInWithdrawal[$val['shop_id']] ?? '0.00';  // 提现中佣金
            $shopsInfo[$key]['leader_withdrawable_commission'] = $leaderWithdrawableCommission[$val['shop_id']] ?? '0.00';   // 可提现佣金
//            $shopsInfo[$key]['leader_total_commission'] = bcadd((string)bcadd((string)$shopsInfo[$key]['commission_to_be_settled'], (string)$shopsInfo[$key]['commission_in_withdrawal'], 2), (string)$shopsInfo[$key]['leader_withdrawable_commission'], 2);   // 团长佣金合计 = 待结算佣金+提现中佣金+团长可提现佣金=团长佣金合计
            $shopsInfo[$key]['leader_total_commission'] = $this -> commissionOfTheLeader(null, $val['shop_id']);
        }

        return ['code' => ErrorCode::SUCCESS, 'data' => $shopsInfo];
    }


    /**
     * 店铺下活跃团长数量
     *
     * @return array
     * 说明：团长下只要有订单，就算是活跃团长
     */
    public function getActiveLeaderInShop()
    {
        $res = OrderModel::query()
            ->selectRaw('
                shop_id,
                COUNT(distinct(leader_id)) as leader_num
            ')
            ->groupBy(['shop_id'])
            ->where('platform_type', 2)
            ->pluck('leader_num', 'shop_id')->toArray();

        return $res;

    }

    /**
     * 获取团长待核销订单数
     * @param null $time
     * @param null $leaderId
     * @return mixed
     */
    public function getLeaderToBeWrittenOffNum($time = null, $leaderId = null)
    {
        $res = OrderModel::query()
            ->selectRaw('
                COUNT(distinct(order_no)) as order_num
            ')
            ->where('leader_id', $leaderId)
            ->where('platform_type', 2)
            ->where('is_pay', 1)
            ->whereIn('status', [2, 3])
            ->when($time ?? 0, function ($query, $time) {
                return $query->whereDate('create_at', $time);
            })
            ->first()->toArray();

        return $res['order_num'];
    }

    /**
     * 获取团长某天核销订单金额
     * @param null $time
     * @param null $leaderId
     * @return mixed
     */
    public function LeaderOrderWriteOffAmount($time = null, $leaderId = null,$shop_id = null)
    {
        $res = OrderModel::query()
            ->selectRaw('
                order_no,
                total_price
            ')
            ->when($shop_id, function ($query, $shop_id) {
                return $query->where('shop_id', $shop_id);
            })
            ->when($leaderId, function ($query, $leaderId) {
                return $query->where('leader_id', $leaderId);
            })
            ->where('platform_type', 2)
            ->where('write_off_code_status', 2)
//            ->whereDate('complete_date', '2020-12-07')
            ->when($time ?? 0, function ($query, $time) {
                return $query->whereDate('complete_date', $time);
            })
            ->get()->toArray();

        // 获取订单所有退款金额
        $orderNos = array_column($res, 'order_no');
        $kzRefund = KzRefundLogModel::query() ->selectRaw("
                SUM(refund_balance_money) as refund_money
            ")
            -> whereIn('order_no',$orderNos)
            -> first() -> toArray();
        $wxRefund = WxRefundLogModel::query() ->selectRaw("
                SUM(refund_wx_money) as refund_money
            ")
            -> whereIn('order_no',$orderNos)
            -> first() -> toArray();
        $kzRefundMoney = $kzRefund['refund_money'] ?? '0.00';
        $wxRefundMoney = $wxRefund['refund_money'] ?? '0.00';
        $writeOffMoney = $this -> multiArraySum($res,'total_price');
        $refundMoney = bcadd((string)$kzRefundMoney,(string)$wxRefundMoney,2);
        $finalMoney = bcsub((string)$writeOffMoney,(string)$refundMoney,2);

        return $finalMoney;
    }

    /**
     * 计算二维数组某个值的合
     * @param array $arr    二维数组
     * @param string $key   需要对某个键进行求和运算
     * @return int|mixed
     */
    function multiArraySum(array $arr, string $key)
    {
        if ($arr)
        {
            $sum_no = 0;
            foreach($arr as $v)
            {
                $sum_no +=  $v[$key];
            }
            return $sum_no;
        } else {
            return 0;
        }
    }

    /**
     * 团长佣金合计
     * @param null $time
     * @param null $leaderId
     * @return float|mixed
     */
    public function LeaderTotalCommission($time = null, $leaderId = null)
    {
        $res = OrderModel::query()
            ->selectRaw('
                SUM(order_commission) as commission_price
            ')
            ->whereDate('complete_date', '=',$time)
            ->where('leader_id', $leaderId)
            ->first()->toArray();
        // 计算退佣金
        $refund = TeamLeaderCommissionRecord::query()
            ->selectRaw("
                (CONVERT(SUM(expend) / 100,DECIMAL(10,2))) as expend
            ")
            ->where('type', 3)
            ->whereDate('created_at', '=',$time)
            ->where('leader_id', $leaderId)
            ->first()->toArray();
        $commission = $res['commission_price'] ?? '0.00';
        $refund = $refund['expend'] ?? '0.00';
        $finalMoney = bcsub((string)$commission,(string)$refund,2);

        return $finalMoney;

    }

    /**
     * 团长可提现佣金合计
     * @param $leaderId
     * @return string|null
     */
    public function totalWithdrawableCommissionByLeader($leaderId)
    {
        $res = TeamLeaderModel::query()
            ->select(
                ['commission_amount', 'frozen_amount']
            )
            ->where('id', $leaderId)
            ->get()->toArray();
        $FreezeOrderCommission = $this -> getFreezeOrderCommission($leaderId);
        $balance = bcdiv((string)bcsub((string)bcsub((string)$res[0]['commission_amount'], (string)$res[0]['frozen_amount'], 2), (string)$FreezeOrderCommission, 2), '100', 2);

        return $balance;
    }

    /**
     * 团长冻结金额
     * @param $leaderId
     * @return string|null
     *
     * 说明：提现中冻结 + 已完成但没过售后期的佣金
     */
    public function totalFrozenCommissionByLeader($leaderId)
    {
        $res = TeamLeaderModel::query()->where('id', $leaderId)->value('frozen_amount');    // 提现中冻结
        $FreezeOrderCommission = $this -> getFreezeOrderCommission($leaderId);   // 已完成，没过售后期

        return bcdiv((string)bcadd((string)$res ?? 0.00, (string)$FreezeOrderCommission, 2),'100', 2);
    }

    /**
     * 团长详情--团长订单
     * @param array $params
     * @param int $perPage
     * @param string[] $field
     * @return array
     *
     * refund_money
     */
    public function leaderOrder($params = [], $perPage = 15, $field = ['*'])
    {
        $order = OrderModel::query()
            ->selectRaw('
                order_no,
                total_price,
                order_commission,
                status,
                pay_at,
                complete_date
            ')
            ->where('platform_type', 2)
            ->where('leader_id', $params['leader_id'])
            ->when($params['order_no'] ?? 0, function ($query, $orderNo) {
                return $query->where('order_no', '=', $orderNo);
            })
            ->latest('pay_at')
            ->paginate($perPage);

        $orderArr = $order->toArray()['data'];
        $orderIds = array_column($orderArr,'order_no');

        // 查出订单中的一件商品
        $orderGoods = OrderGoodsModel::query()
            ->select(['order_no','goods_title'])
            ->whereIn('order_no',$orderIds)
            ->groupBy(['order_no'])
            ->pluck('goods_title','order_no')->toArray();

        //退款金额
        $refundAmount = $this -> getAmountOfRefundMoneyByOrderNo($orderIds);
        foreach ($order as $key => $val){
            $order[$key]['refund_money'] = $refundAmount[$val -> order_no] ?? '0.00';
            $order[$key]['order_goods'] = $orderGoods[$val -> order_no] ? $orderGoods[$val -> order_no].' 等商品' : '';
        }

        return ['code' => ErrorCode::SUCCESS, 'data' => $order];
    }

    /**
     * 团长详情--团长提现记录
     * @param array $params
     * @param int $perPage
     * @param string[] $field
     * @return array
     */
    public function WithdrawalRecordOfLeader($params = [], $perPage = 15, $field = ['*'])
    {
        $query = TeamLeaderCommissionRecord::query();
        if (in_array($params['withdraw_status'], ['0', '1'])) {
            $query->where('tr.withdraw_status', '=', $params['withdraw_status']);
        }

        $res = $query
            ->from('hf_team_leader_commission_record as tr')
            ->leftJoin('hf_team_leader as t', 't.id', '=', 'tr.leader_id')
            ->selectRaw('
                tr.id,
                t.name,
                tr.serial_no,
                tr.created_at,
                tr.withdraw_time,
                t.account_name,
                t.account_bank,
                t.bank_card_number,
                (CONVERT(tr.expend / 100,DECIMAL(10,2))) as expend,
                tr.withdraw_status
            ')
            ->where('tr.type',1)
            ->where('tr.leader_id', $params['leader_id'])
            ->when($params['serial_no'] ?? 0, function ($query, $serialNo) {
                return $query->where('tr.serial_no', '=', $serialNo);
            })
            ->latest('tr.created_at')
            ->paginate($perPage);

        if (!$res->isEmpty()) {
            $bankName = $this->getBankList();
            foreach ($res as $key => $val) {
                $val->account_bank = $bankName[$val->account_bank]['name'] ?? '未知';
            }
        }

        return ['code' => ErrorCode::SUCCESS, 'data' => $res];
    }
    /**
     * 获取团长信息
     * @param int $tid
     * @param string[] $field
     * @return array
     */
    public static function getTeamLeaderInfo(int $tid, $field = ['*'])
    {
        $teamLeader = TeamLeaderModel::where(['id' => $tid])->select($field)->first();
        return $teamLeader ? $teamLeader->toArray() : [];
    }

    /**
     * 根据店铺id获取团长商品总数
     * @param int $shop_id
     * @return array
     */
    public static function sortingGoodsNumber(int $shop_id)
    {
        $num = LeaderSorting::query()->where(['shop_id'=>$shop_id])->sum('num');
        return $num ;
    }

    /**
     * 根据店铺id获取团长已分拣商品总数
     * @param int $shop_id
     * @param array $leader_id
     * @return array
     */
    public static function endSortingGoodsNumber(int $shop_id)
    {
        $num = LeaderSorting::query()->where(['shop_id'=>$shop_id])->whereIn('status',[2,3])->sum('num');
        return $num;
    }

    /**
     * 根据店铺id获取团长待分拣商品类数
     * @param int $shop_id
     * @param array $leader_id
     * @return array | int
     */
    public static function notSortingGoodsNumber(int $shop_id)
    {
        $num = LeaderSorting::query()->where(['shop_id'=>$shop_id])->whereIn('status',[1,2])->count('goods_id');
        return $num ;
    }
}
